Compare commits

...

3844 Commits

Author SHA1 Message Date
Steven 71263736b0 chore: fix codeowners 2026-02-23 20:10:18 +08:00
Mudkip ff3e4c5cfe fix: avoid truncating memo batch attachments (#5654) 2026-02-23 20:09:39 +08:00
Steven 9ecd7b876b fix(web): fix spurious logout on page reload with expired access token
Two bugs caused users to be redirected to /auth too frequently:

1. Race condition in Promise.all([initInstance(), initAuth()]):
   initInstance() makes a gRPC request whose auth interceptor calls
   getAccessToken() synchronously. When the access token was expired,
   getAccessToken() eagerly deleted it from localStorage as a "cleanup"
   side-effect. By the time initAuth() ran and checked hasStoredToken(),
   localStorage was already empty, so it skipped the getCurrentUser()
   call and the token refresh cycle entirely — logging the user out even
   when the refresh-token cookie was still valid. Fix: remove the
   localStorage deletion from getAccessToken(); clearAccessToken()
   (called on confirmed auth failure and logout) handles proper cleanup.

2. React Query retry: 1 caused a second refresh+redirect attempt after
   auth failures. The auth interceptor already handles token refresh and
   request retry internally. If it still throws Unauthenticated, the
   redirect is already in flight — a React Query retry only fires another
   failed refresh and a redundant redirectOnAuthFailure() call. Fix: use
   a shouldRetry function that skips retries for Unauthenticated errors
   while keeping the existing once-retry behaviour for other errors.
2026-02-23 14:08:59 +08:00
Steven 03c30b8ccb fix(web): fix explore page showing private tags and improve stats hook
The explore page sidebar was showing tags from the current user's private
memos because the default ListMemos query applies a server-side OR filter
(creator_id == X || visibility in [...]), mixing private content in.

Fix by using a visibility-scoped ListMemos request in the explore context
so private memos are always excluded via the AND'd server auth filter.

Also consolidate two always-firing useMemos calls into one context-aware
query, unify activity stats computation with countBy across all branches,
and extract a toDateString helper to remove duplicated formatting logic.
2026-02-23 13:15:01 +08:00
Steven 1cea9b0a78 fix(web): make MonthNavigator month label reactive to language changes
Use useTranslation() hook instead of the static i18n import so that
the month label re-computes when the language changes.
2026-02-23 11:04:04 +08:00
Steven 704503e556 fix(store): allow memo/attachment deletion when local file is missing
Fixes two bugs reported in #5603:

1. store/attachment.go: ignore os.ErrNotExist when removing a local
   attachment file so that a missing file on disk (broken state from
   failed uploads) no longer blocks deletion of the DB record, allowing
   memos referencing corrupt attachments to be deleted normally.

2. memo_attachment_service.go: add nil guard on GetAttachment result
   before dereferencing it in SetMemoAttachments, preventing a nil
   pointer panic when an attachment UID no longer exists in the DB.
2026-02-23 10:26:40 +08:00
Steven 17fc8383df fix(web): improve MemoEditor layout and timestamp popover styling 2026-02-23 10:20:00 +08:00
Steven 150371d211 fix(webhook): remediate SSRF vulnerability in webhook dispatcher
- Add plugin/webhook/validate.go as single source of truth for SSRF
  protection: reserved CIDR list parsed once at init(), isReservedIP(),
  and exported ValidateURL() used at registration/update time
- Replace unguarded http.Client in webhook.go with safeClient whose
  Transport uses a custom DialContext that re-resolves hostnames at
  dial time, defeating DNS rebinding attacks
- Call webhook.ValidateURL() in CreateUserWebhook and both
  UpdateUserWebhook paths to reject non-http/https schemes and
  reserved/private IP targets before persisting
- Strip internal service response body from non-2xx error log messages
  to prevent data leakage via application logs
2026-02-23 10:14:24 +08:00
Steven f43965de00 chore: bump version 2026-02-22 18:06:58 +08:00
Steven c3061002f3 fix(web): persist auth token in localStorage for cross-tab sessions
Switch from sessionStorage to localStorage so the auth token survives
across tabs and browser restarts, matching standard platform behavior.
Also guard the signup redirect in App.tsx behind profileLoaded to avoid
a false redirect when the instance profile fetch fails.
2026-02-22 13:55:46 +08:00
Steven 4aaebc507e fix(web): skip GetCurrentUser on init when no token is stored
When no token exists in sessionStorage, AuthContext.initialize() was
still calling GetCurrentUser, triggering the auth interceptor to attempt
RefreshToken and retry — producing a burst of 5+ auth API calls in under
a second that reverse proxies with rate limiting (e.g. CrowdSec) flag as
brute force.

Add hasStoredToken() to auth-state and bail out of initialize() early
when there is definitively no session to restore. The refresh flow for
expired tokens is preserved since hasStoredToken() checks for presence
regardless of expiry.

Fixes #5647
2026-02-22 13:40:34 +08:00
Steven b8bca6bacf fix(web): scope task list item index to memo content container
The closest() selector was targeting a CSS class that never existed on
the container, causing fallback to document.body and collecting task
items across all visible memos. This caused index collisions when
multiple memos with todo lists were on the page.

Adds data-memo-content attribute to the container and updates the
selector accordingly.

Fixes #5635
2026-02-22 13:20:29 +08:00
Steven 2ab476ef2e fix(web): memoize useNavigateTo to prevent infinite view transition loop
Wrapping the returned function in useCallback prevents a new reference
on every render, which was causing an infinite startViewTransition loop
on the initial signup page (fresh install with no admin).

Fixes #5626
2026-02-22 13:16:59 +08:00
Steven 6eaab52e48 fix(web): handle delete memo errors and only run post-delete actions on success 2026-02-22 13:00:36 +08:00
milvasic 1d9d4cd797 fix: invalidate comments query on comment reaction and delete (#5641) 2026-02-22 12:58:56 +08:00
Kaki021 122ac94273 fix(web): ensure default memo visibility is correctly applied (#5623) 2026-02-14 16:58:58 +08:00
Steven 861b58cbf3 refactor(web): extract NsfwOverlay into standalone component with flexbox centering 2026-02-12 23:19:54 +08:00
Steven aeb1e5fe40 perf(web): eliminate redundant fetch when opening inline memo editor 2026-02-12 23:02:25 +08:00
Steven 69485eecb3 chore: tweak readme 2026-02-12 22:35:58 +08:00
Johnny 6402618c26 feat(web): replace EditableTimestamp with inline editor timestamp popover 2026-02-11 23:45:53 +08:00
Johnny 566fdccae6 fix(web): allow calendar year picker to go back to 1970 2026-02-11 22:58:25 +08:00
Johnny 177a74e82b fix: allow ampersand in tags to support compound tags 2026-02-11 22:55:45 +08:00
boojack f7d370dba1 chore: tweak readme
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-02-10 23:04:35 +08:00
Steven 47e2ace690 fix(web): redirect to auth page instead of explore on session expiry
Fixes #5617
2026-02-10 21:15:44 +08:00
Steven 27063d4850 chore(ci): auto-upload binaries to GitHub Release on publish 2026-02-10 20:51:05 +08:00
Steven 71e8a06463 chore: upgrade Echo v4 to v5.0.3 2026-02-10 09:15:27 +08:00
boojack cdadead6c9 chore: add SSD Nodes sponsorship
Signed-off-by: boojack <stevenlgtm@gmail.com>
2026-02-10 08:27:18 +08:00
Steven 2b19d8a969 fix(tests): update PAT tests to accept both custom and SQL errors
The PostgreSQL implementation returns 'PAT not found' when no rows match,
while SQLite/MySQL return 'sql: no rows in result set' from QueryRowContext.

Both behaviors are correct - the key fix is that PostgreSQL no longer
throws JSONB errors on missing/malformed data.

Changes:
- Update test assertions to accept either error type
- Fix comment punctuation for godot linter
- Maintain backward compatibility across all database drivers
2026-02-09 21:09:19 +08:00
Steven d9e8387d63 fix(postgres): handle missing PAT data gracefully and add comprehensive tests
Fixes #5612, #5611

Root cause: PostgreSQL's jsonb_array_elements() throws errors when the
'tokens' key is missing or malformed, while SQLite/MySQL return NULL
gracefully. This caused:
- 502 errors when creating admin after v0.25.3 → v0.26.0 upgrade
- Settings not persisting and users unable to stay logged in

Changes to store/db/postgres/user_setting.go:
- Remove strict JSONB operations from GetUserByPATHash query
- Fetch all PERSONAL_ACCESS_TOKENS rows and filter in Go
- Skip malformed/invalid JSON rows with continue (error recovery)
- Match SQLite/MySQL's forgiving error handling

New integration tests (store/test/user_setting_test.go):
- TestUserSettingGetUserByPATHashNoTokensKey
- TestUserSettingGetUserByPATHashEmptyTokensArray
- TestUserSettingGetUserByPATHashWithOtherUsers

New PostgreSQL-specific tests (store/db/postgres/user_setting_test.go):
- TestGetUserByPATHashWithMissingData (comprehensive edge cases)
- TestGetUserByPATHashPerformance (100+ users)
- TestUpsertUserSetting (basic upsert)

Test coverage:
 Missing PERSONAL_ACCESS_TOKENS key
 Empty/malformed JSON data
 Multiple users with mixed valid/invalid data
 Performance with 100+ users
 Error recovery without crashes

Benefits:
- No database migration required (TEXT column works fine)
- Backward compatible with v0.25.3 upgrades
- Handles missing/corrupt data gracefully
- Consistent behavior across all database drivers
2026-02-09 21:02:09 +08:00
MuLingQwQ b5108b4f97 fix(web): calendar navigation should use current page path (#5605) 2026-02-09 20:40:12 +08:00
Johnny b623162d37 chore: fix static check linter warnings 2026-02-08 21:37:02 +08:00
Johnny ba615172b0 chore: bump version 2026-02-08 21:28:11 +08:00
Johnny 984d9b461b fix: gracefully handle deleted memos in activity service to prevent inbox crashes 2026-02-08 21:26:18 +08:00
Johnny a69056a1c2 fix: handle underscores in environment variables correctly 2026-02-08 20:38:43 +08:00
Johnny f827296d6b chore: fix broken links 2026-02-08 19:46:03 +08:00
Johnny d9dc5be200 fix: replace echo.NewHTTPError with status.Errorf 2026-02-08 19:23:34 +08:00
Johnny c4176b4ef1 fix: videos attachment 2026-02-07 16:03:52 +08:00
Steven 81ef53b398 fix: prevent 401 errors on window focus when token expires
Fixes #5589

When the page returns from background to foreground after the JWT
token expires (~15 min), React Query's automatic refetch-on-focus
triggers multiple API calls simultaneously. These all fail with 401
Unauthorized, leaving the user with empty content.

Solution:
- Add useTokenRefreshOnFocus hook that listens to visibilitychange
- Proactively refresh token BEFORE React Query refetches
- Uses 2-minute buffer to catch expiring tokens early
- Graceful error handling - logs error but doesn't block

Changes:
- Created web/src/hooks/useTokenRefreshOnFocus.ts
- Updated isTokenExpired() to accept optional buffer parameter
- Exported refreshAccessToken() for use by the hook
- Integrated hook into AppInitializer (only when user authenticated)
2026-02-05 22:14:48 +08:00
Steven 86f780d1a4 chore: tweak security report email 2026-02-05 19:43:19 +08:00
Steven cf65f0867b refactor: remove hide-scrollbar utility
Removed the hide-scrollbar CSS class and all its usages throughout the
codebase. Hiding scrollbars can hurt UX by making it unclear when
content is scrollable.

Changes:
- Removed hide-scrollbar CSS definition from index.css
- Removed hide-scrollbar class from Navigation component (2 instances)
- Removed hide-scrollbar class from MemoDetailSidebar (2 instances)
- Removed hide-scrollbar class from TagsSection
- Removed hide-scrollbar class from ShortcutsSection

Components now use standard browser scrollbar behavior, which provides
better visual feedback to users about scrollable content. Modern
browsers already handle scrollbar appearance elegantly.
2026-02-04 20:24:54 +08:00
Steven 74b63b278c perf: disable tooltips in year calendar to fix lag
Fixed issue #5579 where the calendar selection dialog was very laggy.

The root cause was rendering ~365 individual Tooltip components when
opening the year calendar view (one per day with activity). This created
a huge number of DOM nodes and event listeners that caused significant
performance issues.

Changes:
- Added disableTooltips prop to MonthCalendar and CalendarCell components
- Disabled tooltips in YearCalendar's small month views
- Removed unnecessary TooltipProvider wrapper in YearCalendar
- Tooltips remain enabled in the default month calendar view

Performance improvements:
- Eliminates ~365 tooltip instances when dialog opens
- Reduces initial render time significantly
- Makes dialog interactions smooth and responsive

Users can still click on dates to drill down for details if needed.
2026-02-04 20:14:55 +08:00
Steven e7605d90da fix: shortcut edit button opens create dialog instead of edit dialog
Fixed issue #5576 where clicking the edit button on a shortcut would
incorrectly open a create dialog instead of an edit dialog.

The root cause was an incorrect useEffect that was watching the shortcut
state itself instead of the initialShortcut prop. When the dialog was
opened for editing, the state wasn't properly reinitializing with the
existing shortcut data.

Changed the useEffect to:
- Watch initialShortcut as the dependency
- Reinitialize the shortcut state when initialShortcut changes
- Properly distinguishes between create (initialShortcut undefined) and
  edit (initialShortcut has data) modes
2026-02-04 20:03:53 +08:00
memory_clear f9bf903eea chore: update access token deletion message description for zh-Hans (#5573)
Signed-off-by: memory_clear <83893503+MemoryClear@users.noreply.github.com>
2026-02-04 19:54:51 +08:00
Steven 6bb383a4a5 fix: prevent CTRL+Enter save while editor is loading content (#5581)
- Add validation check for loading state before allowing save
- Prevents false "Content, attachment, or file required" error
- Occurs when user presses CTRL+Enter immediately after opening edit mode
- Editor state may still be loading when keyboard shortcut fires

Closes #5581
2026-02-03 23:55:07 +08:00
Steven b4fea8c647 fix: nested task list display and checkbox interaction (#5575)
- Fix nested task lists not showing proper indentation
- Use simple CSS cascade with [&_ul.contains-task-list]:ml-6
- Fix checkbox clicks toggling wrong tasks in nested lists
- Search from memo root container for global task indexing
- Remove complex selectors in favor of standard approach
- Match behavior of GitHub, Notion, and other platforms

Closes #5575
2026-02-03 23:45:45 +08:00
Steven cf0a285ef1 fix(auth): make PKCE optional for OAuth sign-in (#5570)
Fixes issue where OAuth sign-in fails with 'Cannot read properties of
undefined (reading 'digest')' when accessing Memos over HTTP.

The crypto.subtle API is only available in secure contexts (HTTPS or
localhost), but PKCE (RFC 7636) is optional per OAuth 2.0 standards.

Changes:
- Make PKCE generation optional with graceful fallback
- Use PKCE when crypto.subtle available (HTTPS/localhost)
- Fall back to standard OAuth flow when unavailable (HTTP)
- Log warning to console when PKCE unavailable
- Only include code_challenge in auth URL when PKCE enabled

The backend already supports optional PKCE (empty codeVerifier), so no
backend changes needed. This fix aligns frontend behavior with backend.

Benefits:
- OAuth sign-in works on HTTP deployments (reverse proxy scenarios)
- Enhanced security (PKCE) still used when HTTPS available
- Backward compatible with OAuth providers that don't support PKCE

Fixes #5570
2026-02-02 23:28:21 +08:00
Steven 7465fbb4cc refactor: improve GitHub Actions workflows structure and maintainability
- Add build-binaries workflow for multi-platform binary releases
- Rename workflows for conciseness:
  - demo-render-deploy.yml → demo-deploy.yml
  - build-and-push-canary-image.yml → build-canary-image.yml
  - build-and-push-stable-image.yml → build-stable-image.yml
- Centralize version config with env variables (GO_VERSION, NODE_VERSION, PNPM_VERSION)
- Standardize step names across all workflows
- Add concurrency controls to prevent redundant runs
- Update Node.js (20→22) and pnpm (9→10) versions to match build-binaries
- Improve job names with descriptive labels
- Add consistent comments and formatting
- Set artifact retention to 60 days for binary builds
2026-02-02 23:15:15 +08:00
Steven 4033f64b9a feat: add build binaries workflow for multi-platform releases
- Add workflow_dispatch trigger for manual binary builds
- Build for linux (amd64, arm64, arm/v7), darwin (amd64, arm64), windows (amd64)
- Package as tar.gz (Unix) and zip (Windows)
- Generate build summary with artifact sizes
2026-02-02 22:54:30 +08:00
Steven 29412f4690 refactor: simplify NSFW implementation by inlining logic
- Remove unused showNsfwContent prop (was only used in MemoDetail to pre-reveal NSFW, which defeats the purpose)
- Inline useNsfwContent hook logic directly into MemoView.tsx (only 3 lines, no reusability benefit)
- Delete web/src/components/MemoView/hooks/useNsfwContent.ts
- NSFW content now consistently starts hidden across all pages
- Maintains same user experience: click to reveal, no toggle back

This removes unnecessary indirection and prop threading while preserving functionality.
2026-02-02 22:06:04 +08:00
Steven 6db58fae11 fix: prevent private memos from disappearing during token refresh (#5565)
Root cause: enabled={isInitialized && !!user} prevented displaying cached
data when user auth state transitioned during token refresh.

Changes:
- Remove !!user check from Home page enabled condition
- Add clearAccessToken() in redirectOnAuthFailure for clean logout

Fixes #5565
2026-02-02 21:45:24 +08:00
Steven 8770b186e4 fix: add Unicode case-insensitive search for SQLite (#5559)
Add custom memos_unicode_lower() SQLite function to enable proper
case-insensitive text search for non-English languages (Cyrillic,
Greek, CJK, etc.).

Previously, SQLite's LOWER() only worked for ASCII characters due to
modernc.org/sqlite lacking ICU extension. This caused searches for
non-English text to be case-sensitive (e.g., searching 'блины' wouldn't
find 'Блины').

Changes:
- Add store/db/sqlite/functions.go with Unicode case folding function
- Register custom function using golang.org/x/text/cases.Fold()
- Update filter renderer to use custom function for SQLite dialect
- Add test for Unicode case-insensitive search
- Make golang.org/x/text a direct dependency

Fixes #5559
2026-02-02 21:10:07 +08:00
Damian Jankowski c14843fa62 chore: view memo URL updated (#5569) 2026-02-02 20:39:33 +08:00
Steven 2db57b139a fix: handle pasted files in memo editor
Fixes #5568
2026-02-02 20:36:08 +08:00
Steven 0dbc35a2ba fix: restore access token creation flow
Fixes #5563
2026-02-02 20:31:22 +08:00
Steven e1c8101d29 fix: preserve tag case when extracting markdown tags
Fixes #5566
2026-02-02 20:07:06 +08:00
Steven 34c341c88c chore: fix update user request name in member dialog
Fixed #5564
2026-02-02 19:52:46 +08:00
Steven b8029c70ef chore: fix OAuth callback double-run state error 2026-02-02 09:07:55 +08:00
Johnny d14cfa1c4f fix: auto-fix permission issues when upgrading from 0.25.3 to 0.26.0
Fixes #5551

The Docker image now runs as non-root (UID 10001) for security, but this
breaks upgrades from 0.25.3 where data files were owned by root.

Changes:
- Dockerfile: Keep USER as root, install su-exec
- entrypoint.sh: Fix ownership of /var/opt/memos, then drop to non-root
- Supports custom MEMOS_UID/MEMOS_GID env vars for flexibility

This allows seamless upgrades without manual chown on the host.
2026-02-01 08:37:06 +08:00
Johnny 1696c6c414 fix: add nil check for currentUser in DeleteUser
Defense-in-depth fix: Add missing nil check before accessing
currentUser.ID and currentUser.Role in DeleteUser function.

While the auth interceptor should block unauthenticated requests,
this check prevents potential nil pointer panic if fetchCurrentUser
returns (nil, nil).
2026-01-31 23:08:09 +08:00
Johnny c7b48b800f fix: add access control checks for attachments, comments, and reactions
Security fixes for multiple authorization bypass vulnerabilities:

- GetAttachment: Add visibility check via checkAttachmentAccess helper
- UpdateAttachment: Add ownership check (creator or admin only)
- Fileserver: Require creator/admin auth for unlinked attachments
- ListMemoAttachments: Add memo visibility check
- CreateMemoComment: Add memo visibility check for target memo
- ListMemoReactions: Add memo visibility check
- UpsertMemoReaction: Add memo visibility check

All checks follow the existing pattern used in GetMemo for consistency.
2026-01-31 23:02:30 +08:00
Johnny 86fab0cf4c fix(fileserver): use streaming for video/audio to prevent memory exhaustion
- Add serveMediaStream() to stream video/audio without loading into memory
- Use http.ServeFile for local files (zero-copy, handles range requests)
- Redirect to S3 presigned URLs for S3-stored media files
- Refactor for better maintainability:
  - Extract constants and pre-compile lookup maps
  - Consolidate duplicated S3 client creation logic
  - Split authentication into focused helper methods
  - Group code by responsibility with section comments
  - Add setSecurityHeaders() and setMediaHeaders() helpers
2026-01-31 22:01:28 +08:00
Ganesh M 27de96d440 fix(ui): math render (#5549) 2026-01-31 21:46:19 +08:00
Johnny 8cd9c591d4 chore: deprecate remove completed tasks action
- Remove menu item and dialog from MemoActionMenu
- Remove removeCompletedTasks() and hasCompletedTasks() utilities
- Remove translation keys from all 34 locale files
- Feature was not aligned with standard note-taking UX patterns
2026-01-31 21:03:05 +08:00
Johnny 5396c126b8 chore: extract task list class names to constants
- Add TASK_LIST_CLASS and TASK_LIST_ITEM_CLASS constants
- Replace hardcoded 'contains-task-list' and 'task-list-item' strings
- Improve maintainability and prevent typos
2026-01-31 20:53:55 +08:00
Johnny 97ba15450f chore: prevent unnecessary API calls when timestamp unchanged in MemoDetailSidebar
- Add same value check before updating createTime/updateTime
- Skip request if new timestamp equals current timestamp
- Simplify callback handlers and improve code readability
- Use .some() instead of .filter().length for cleaner code
2026-01-31 15:12:27 +08:00
Johnny f7a81296fb style: enhance ActivityCalendar components with improved styling and layout adjustments 2026-01-30 00:13:58 +08:00
Johnny fcb9e377c1 chore: streamline memo editor insert menu 2026-01-29 23:34:40 +08:00
Steven b32cba35c6 fix: add nil check for AnyResponse in WrapUnary method to prevent caching issues 2026-01-29 21:32:54 +08:00
Steven b0558824c4 feat: update instance profile to use admin user instead of initialized flag
- Changed InstanceProfile to include admin user field
- Updated GetInstanceProfile method to retrieve admin user
- Modified related tests to reflect changes in admin user retrieval
- Removed owner cache logic and tests, introducing new admin cache tests
2026-01-28 23:27:53 +08:00
Johnny 81022123a1 chore: simplify page loading logic 2026-01-27 23:37:32 +08:00
cui c5d9770fd1 typo: lenght to length (#5539) 2026-01-27 22:21:55 +08:00
Johnny 6731eccded feat: add EditableTimestamp component for inline date editing in MemoDetailSidebar 2026-01-26 23:23:14 +08:00
Johnny a7b0d71f6e feat: implement EXIF metadata stripping for image uploads 2026-01-26 22:18:44 +08:00
Brent Bilis 2f7c8dcea7 fix(ui): correct calendar header month parsing (#5532)
Co-authored-by: Local Admin <root@localhost>
2026-01-26 22:01:11 +08:00
Johnny e1888153f8 chore: polish dark styles 2026-01-26 21:59:36 +08:00
Johnny 98eaff1277 style: adjust spacing and background colors for improved UI consistency across components 2026-01-26 21:49:26 +08:00
Johnny 72c7965c8f chore: enable binary format for transport 2026-01-26 21:16:06 +08:00
Salman Chishti a8dbc1fd5e chore: upgrade GitHub Actions for Node 24 compatibility (#5527)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-01-26 09:02:57 +08:00
itzmk21 f22b3dad25 chore(i18n): update British English spelling (#5529) 2026-01-26 08:48:43 +08:00
Salman Chishti 1e82723e88 chore: upgrade GitHub Actions to latest versions (#5528)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-01-26 08:48:07 +08:00
XIN_____ 45945a1df7 chore: update Chinese translation (#5519) 2026-01-23 23:32:58 +08:00
Pádraic Slattery 7fbf3bed85 chore: update outdated GitHub Actions versions (#5522) 2026-01-23 23:22:14 +08:00
Johnny ad327a4a8d fix: adjust compact mode styling for MemoContent component 2026-01-23 09:11:33 +08:00
Johnny 7154ce0228 feat: implement markdown components for enhanced rendering 2026-01-23 09:04:42 +08:00
Steven c0d6224155 chore: enable compact mode for list view 2026-01-22 22:52:14 +08:00
Steven 6c9ea31de0 chore: add translation for saving status in EditorToolbar 2026-01-22 22:31:19 +08:00
Steven 501e8f1eae chore: implement read-write lock for owner cache 2026-01-22 22:11:47 +08:00
Steven edcddf3c95 chore: fix tests 2026-01-22 21:59:23 +08:00
Steven fd29a98c90 chore: fix linter 2026-01-22 21:03:05 +08:00
Steven ba099b72ed feat: update InstanceProfile to include initialization status
- Removed the owner field from InstanceProfile as it is no longer needed.
- Added an initialized field to InstanceProfile to indicate if the instance has completed first-time setup.
- Updated GetInstanceProfile method to set initialized based on the existence of an admin user.
- Modified tests to reflect changes in InstanceProfile and ensure correct behavior regarding instance initialization.
- Adjusted frontend logic to redirect users based on the initialized status instead of the owner field.
2026-01-22 20:59:40 +08:00
Steven c240b70591 feat: add enabled option to useInfiniteMemos and PagedMemoList for conditional fetching 2026-01-22 20:21:16 +08:00
Steven 956ae0ebc5 fix: prevent browser caching of API responses in MetadataInterceptor 2026-01-21 08:12:23 +08:00
Steven 9cc970a3ea chore: fix data directory handling 2026-01-21 08:02:25 +08:00
Steven 4180613fc0 fix: update demo mode handling 2026-01-21 07:36:30 +08:00
Johnny 324f795965 fix: improve default data directory handling 2026-01-20 23:55:46 +08:00
Johnny d3ed069ddb refactor: remove environment variable binding for instance URL 2026-01-20 23:45:59 +08:00
Johnny 0f3c9a467d refactor: migrate HOST roles to ADMIN
- Updated the isSuperUser function to only check for ADMIN role.
- Added SQL migration scripts for MySQL, PostgreSQL, and SQLite to change user roles from HOST to ADMIN.
- Created a new SQLite migration to alter the user table structure and ensure data integrity during the migration process.
2026-01-20 23:38:30 +08:00
Johnny 47ebb04dc3 refactor: remove mode flag and introduce explicit demo flag 2026-01-20 22:58:33 +08:00
Johnny 05f31e457e fix: add mmap size setting to database connection to prevent OOM errors 2026-01-20 21:53:31 +08:00
Johnny 552318209b fix: resolve flaky migration tests and add stable upgrade test (#5514) 2026-01-20 19:25:00 +08:00
Steven 00f21b86e2 chore: remove redundant tests 2026-01-20 09:12:36 +08:00
Steven d8b5bd61ab chore: tweak sponsor assets 2026-01-20 08:58:25 +08:00
Johnny 7089db06c2 test: enhance memo filter tests with COALESCE for JSON extraction and add migration data persistence tests 2026-01-19 23:09:17 +08:00
Johnny af2a2588bf chore(test): add edge case tests for user settings shortcuts and JSON fields 2026-01-19 22:50:14 +08:00
Johnny dc7ec8a8ad feat: allow setting custom timestamps when creating memos and comments
Allow API users to set custom create_time, update_time, and display_time
when creating memos and comments. This enables importing historical data
with accurate timestamps.

Changes:
- Update proto definitions: change create_time and update_time from
  OUTPUT_ONLY to OPTIONAL to allow setting on creation
- Modify CreateMemo service to handle custom timestamps from request
- Update database drivers (SQLite, MySQL, PostgreSQL) to support
  inserting custom timestamps when provided
- Add comprehensive test coverage for custom timestamp functionality
- Maintain backward compatibility: auto-generated timestamps still
  work when custom values are not provided
- Fix golangci-lint issues in plugin/filter (godot and revive)

Fixes #5483
2026-01-17 12:56:03 +08:00
Johnny cbf46a2988 feat(filter): add CEL list comprehension support for tag filtering
Add support for CEL exists() comprehension with startsWith, endsWith, and
contains predicates to enable powerful tag filtering patterns.

Features:
- tags.exists(t, t.startsWith("prefix")) - Match tags by prefix
- tags.exists(t, t.endsWith("suffix")) - Match tags by suffix
- tags.exists(t, t.contains("substring")) - Match tags by substring
- Negation: !tags.exists(...) to exclude matching tags
- Works with all operators (AND, OR, NOT) and other filters

Implementation:
- Added ListComprehensionCondition IR type for comprehension expressions
- Parser detects exists() macro and extracts predicates
- Renderer generates optimized SQL for SQLite, MySQL, PostgreSQL
- Proper NULL/empty array handling across all database dialects
- Helper functions reduce code duplication

Design decisions:
- Only exists() supported (all() rejected at parse time with clear error)
- Only simple predicates (matches() excluded to avoid regex complexity)
- Fail-fast validation with helpful error messages

Tests:
- Comprehensive test suite covering all predicates and edge cases
- Tests for NULL/empty arrays, combined filters, negation
- Real-world use case test for Issue #5480 (archive workflow)
- All tests pass on SQLite, MySQL, PostgreSQL

Closes #5480
2026-01-17 12:36:39 +08:00
zz4zz f600fffe93 fix: use stable memos image tag (#5482) 2026-01-14 23:56:27 +08:00
Johnny 4bd0f29ee5 fix: resolve linter warning and cache race condition
- Suppress revive redundant-test-main-exit warning with //nolint
- Fix data race in cache.Clear() by using Delete() instead of map replacement
- Both changes maintain correct behavior while fixing CI failures
2026-01-14 23:50:37 +08:00
Johnny db57f4456a fix: resolve data races in store tests with atomic operations
Fix all data races detected by -race flag in parallel store tests.

Problems fixed:
1. TestMain not propagating exit code
   - Was: m.Run(); return
   - Now: os.Exit(m.Run())

2. Data races on global DSN variables
   - mysqlBaseDSN and postgresBaseDSN written in sync.Once
   - Read outside Once without synchronization
   - Race detector: write/read without happens-before relationship

3. Data races on container pointers
   - mysqlContainer, postgresContainer, testDockerNetwork
   - Same pattern: write in Once, read in cleanup

Solution: Use atomic operations
- atomic.Value for DSN strings (Store/Load)
- atomic.Pointer for container pointers (Store/Load)
- Provides proper memory synchronization
- Race-free reads and writes

Why sync.Once alone wasn't enough:
- sync.Once guarantees function runs once
- Does NOT provide memory barrier for variables written inside
- Reads outside Once have no synchronization with writes
- Race detector correctly flags this as violation

Technical details:
- atomic.Value.Store() provides release semantics
- atomic.Value.Load() provides acquire semantics
- Guarantees happens-before relationship per Go memory model
- All 159 parallel tests can safely access globals

Impact:
- Tests now pass with -race flag
- No performance degradation (atomic ops are fast)
- Maintains parallel execution benefits (8-10x speedup)
- Proper Go memory model compliance

Related: Issues #2, #3 from race analysis
2026-01-14 23:37:12 +08:00
Johnny e082adf7b6 fix: set DRIVER=sqlite in CI to prevent TestMain from spawning child processes
Problem:
- store/test/TestMain checks if DRIVER env var is set
- If not set, it runs tests for all 3 drivers (sqlite, mysql, postgres)
  by spawning child 'go test' processes
- This conflicts with t.Parallel() in individual tests
- CI workflow didn't set DRIVER, triggering multi-driver execution

Solution:
- Set DRIVER=sqlite in GitHub Actions workflow
- TestMain will run tests once with SQLite driver
- Tests run in parallel with t.Parallel() as intended
- Avoids spawning child processes and race conditions

Why SQLite:
- Fastest test execution (no container startup)
- Sufficient for CI validation
- MySQL/Postgres can be tested locally when needed

This fixes the 'table already exists' errors and test flakiness
in CI while maintaining parallel execution benefits.
2026-01-14 22:50:30 +08:00
Johnny 411e8fc5b0 perf: enable parallel execution for all store tests
Add t.Parallel() to all 159 test functions in store/test/

Benefits:
- Tests run in parallel (8-16 concurrent on typical CI)
- Each test already has isolated database (safe to parallelize)
- No shared state between tests
- Go test runner handles synchronization

Expected performance:
- SQLite tests: 4-6min → 30-45sec (87% faster)
- MySQL tests: 6-8min → 45-60sec (88% faster)
- Better CPU utilization (10-15% → 80-95%)

Why it's safe:
- NewTestingStore() creates isolated DB per test
- No global state mutations
- Each test uses t.TempDir() for file isolation
- Container-based tests use unique database names

Impact on CI workflow:
- Backend tests workflow: 4-6min → 1-2min total
- Store test group: 3-4min → 20-30sec
- 8-10x speedup from parallelization alone
2026-01-14 22:44:19 +08:00
Johnny 07b837b6f6 perf: optimize backend tests with parallel execution
Major improvements:
- Split tests into 4 parallel groups (store, server, plugin, other)
  * 3-4x faster test execution (4-6min → 1-2min)

- Enable golangci-lint cache (was disabled)
  * Saves 20-30s on lint checks

- Remove unnecessary flags
  * check-latest: API call overhead
  * --verbose: unnecessary output
  * skip-cache: disabled caching

- Add race detector (-race)
  * Better concurrency bug detection
  * Only 10-20% overhead

- Add coverage tracking
  * Per-group coverage upload to Codecov
  * Better visibility into test quality

- Add concurrency control
  * Cancel outdated PR runs
  * Saves runner minutes

- Clean up output processing
  * Remove test.log and complex awk/sed parsing
  * GitHub Actions shows output by default

Performance impact:
- Setup: 30s → 10s (2-3x faster)
- Tests: Sequential → 4 parallel jobs (3-4x faster)
- Total: 4-6min → 1-2min (~70% faster)
2026-01-14 22:34:46 +08:00
Johnny d7c5641246 fix: correct manifest merge step in workflows
- Re-run docker/metadata-action in merge job to generate proper JSON
- Use steps.meta.outputs.json instead of needs.prepare.outputs.tags
- Remove unused prepare job outputs (tags, labels)
- Simplify workflow dependency chain

This fixes the jq parse error when creating multi-arch manifests.
2026-01-14 22:28:26 +08:00
Johnny d1d2d86900 perf: optimize CI/CD workflows and Docker builds
- Implement parallel matrix builds for multi-platform images (~50% faster)
- Add pnpm store caching for 20-40s savings on cache hits
- Use --frozen-lockfile for faster, deterministic installs
- Optimize Dockerfile: CGO_ENABLED=0, -trimpath, static linking
- Reduce Docker layers and improve caching strategy
- Enhance .dockerignore to exclude unnecessary files (~1MB saved)

Build time improvements:
- Canary: 12-18min → 6-10min
- Stable: 17-27min → 8-12min
2026-01-14 22:12:28 +08:00
Johnny 253e79c111 style: remove unnecessary font-weight classes for cleaner UI 2026-01-13 23:19:43 +08:00
Steven 73c301072b refactor: simplify editor scroll logic
- Extract `scrollToCaret` helper to deduplicate scroll logic
- Unify precise scroll behavior for both manual triggers and auto-scroll
2026-01-13 21:23:23 +08:00
Steven 4e34ef22bf fix: improve editor auto-scroll and Safari IME handling (#5469)
- Use `textarea-caret` for precise cursor position calculation instead of line approximation
- Update `scrollToCursor` to scroll to the actual cursor position
- Fix Safari double-enter issue with IME in list completion
2026-01-13 21:19:31 +08:00
Steven 61dbca8dc2 fix: prevent browser cache from serving stale memo data (#5470)
This fixes a critical data loss issue where users editing the same memo
on multiple devices would overwrite each other's changes due to aggressive
browser caching, particularly in Chromium-based browsers and PWAs.

Changes:
- Backend: Add Cache-Control headers to all API responses to prevent
  browser HTTP caching
- Frontend: Force fresh fetch from server when opening memo editor by
  invalidating React Query cache
- Frontend: Reduce memo query staleTime from 60s to 10s for better
  collaborative editing support

Fixes #5470
2026-01-13 20:55:21 +08:00
Johnny c45a59549a fix: replace os.Exit with panic for clearer error handling 2026-01-12 23:36:48 +08:00
Johnny 69b62cccdb test: optimize store tests performance by reusing docker image and reducing build context 2026-01-12 23:30:56 +08:00
Johnny f58533003b fix: clean up memo_relation and attachments when deleting memo
Fixes #5472

Move cleanup logic to store.DeleteMemo to ensure data consistency:
- Delete memo_relation records where memo is source (MemoID) or target (RelatedMemoID)
- Delete attachments linked to the memo (including S3/local files)

This prevents stale COMMENT records in memo_relation after deleting
a memo that has comments.
2026-01-12 23:18:04 +08:00
Johnny 6899c2f66a chore: fix golangci-lint 2026-01-12 22:32:38 +08:00
Johnny 31f634b71a chore: add more tests 2026-01-12 22:28:42 +08:00
Johnny 8f9ff5634c chore: remove redundant icon 2026-01-12 09:11:08 +08:00
Johnny 9a3451b9d1 fix(editor): filter RelationList to only show referencing memos
- Filter out COMMENT type relations, only show REFERENCE type
- When editing a memo, only show relations where current memo is the source
- Pass memoName through EditorMetadata to RelationList for filtering
2026-01-11 22:41:20 +08:00
Johnny 7053edae27 fix: allow guests to view public memo comments
Add ListMemoComments to public endpoints whitelist so unauthenticated
users can see public comments. The service layer already filters
comments by visibility (only PUBLIC for guests).

Fixes #5471
2026-01-11 22:35:12 +08:00
Faizaan pochi da2dd80e2f fix: return Unauthenticated instead of PermissionDenied on token expiration (#5454) 2026-01-08 23:21:33 +08:00
Jongho Hong 07eac279d0 chore(i18n): add missing Korean translations (#5456)
Signed-off-by: Jongho Hong <myodan@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-08 23:13:21 +08:00
Johnny 1e8505bfeb chore: fix tests 2026-01-08 23:06:28 +08:00
Johnny af6a0726d8 chore: drop redundant indexes in sqlite migration 2026-01-08 22:53:46 +08:00
Johnny 1985205dc2 chore: remove memo_organizer table 2026-01-08 22:28:13 +08:00
Johnny f4cf2e9559 test: improve migration tests stability and maintainability
- Fix linting issues and address testcontainers deprecation in store/test/containers.go
- Extract MemosStartupWaitStrategy for consistent container health checks
- Refactor migrator_test.go to use a consolidated testMigration helper, reducing duplication
- Add store/test/Dockerfile for optimized local test image builds
2026-01-07 23:04:12 +08:00
Om vataliya 013ea52519 fix: apply theme and locale changes immediately on login screen (#5440) (#5442) 2026-01-07 21:58:47 +08:00
Faizaan pochi 7c3fcc297d fix: allow public memo API access without authentication (#5451) 2026-01-07 20:52:04 +08:00
Johnny 14fb38f375 fix: attachment table name 2026-01-07 20:44:21 +08:00
Johnny c29c1d3e1f fix: seed data 2026-01-07 20:41:16 +08:00
Johnny cc9a214be8 revert: revert system_setting to instance_setting rename changes
Reverts only the system_setting → instance_setting rename related changes from commit d326c71.
Keeps the resource → attachment rename changes intact.

- Reverts table name back to system_setting in all database drivers (MySQL, PostgreSQL, SQLite)
- Removes migration files for the system_setting rename
- Reverts LATEST.sql files to use system_setting table
2026-01-07 20:38:02 +08:00
Johnny e75862de31 chore: fix tests 2026-01-07 09:17:34 +08:00
Johnny 79f1edc9ba chore: bump version 2026-01-07 09:08:20 +08:00
Johnny 9ccb658768 fix: sign up redirect 2026-01-07 08:50:10 +08:00
Johnny 64b487d4af chore: fix seed data 2026-01-07 08:34:42 +08:00
Johnny d326c71078 refactor(db): rename tables for clarity - resource→attachment, system_setting→instance_setting 2026-01-06 23:36:42 +08:00
Johnny 01669685b4 fix(ci): remove invalid revive rule 'use-waitgroup-go' from golangci-lint config 2026-01-06 21:12:40 +08:00
Johnny 1f755f74a4 fix(web): make login screen theme selector reactive
This fixes an issue where the theme selector on the login screen would not update its display value after selection because the component was not re-rendering. Added local state to track the current theme. Validated that this pattern is unique to the unauthenticated context.
2026-01-06 20:51:45 +08:00
Steven fb4f3e70dc fix: resolve golangci-lint issues 2026-01-06 20:41:24 +08:00
Steven e1941e7843 fix: attachment type checks 2026-01-06 20:37:04 +08:00
Faizaan pochi 874a4a7142 fix: KaTeX math rendering with underscores (#5438) 2026-01-06 20:16:01 +08:00
Steven 62646853eb chore: tweak comments display 2026-01-06 19:08:03 +08:00
Steven ed66e0fec2 chore: fix linter 2026-01-06 09:08:27 +08:00
Steven 5a8e1845e2 fix: reaction button in mobile view 2026-01-06 09:06:52 +08:00
Johnny d68ca84832 fix: delete unused attachments by using filter 2026-01-05 22:43:57 +08:00
Johnny 4b110d0d38 fix: cursor position after slash commands 2026-01-05 22:24:13 +08:00
Steven 15646a8989 chore: fix linter 2026-01-05 21:57:07 +08:00
Steven e268a1fe9c chore: tweak memo content renderer 2026-01-05 21:50:49 +08:00
Steven ac37738148 fix: default visibility setting 2026-01-05 21:46:35 +08:00
lif 86013d6c2a fix(scripts): add file existence check in file_env (#5424)
Signed-off-by: majiayu000 <1835304752@qq.com>
2026-01-04 19:18:48 +08:00
lif cbbb585b2e fix(frontend): ensure attachments are properly linked when creating memos (#5428)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 19:17:14 +08:00
Sheep-realms b7b658358e chore: update simplified chinese localization (#5422) 2026-01-04 19:10:24 +08:00
Roman Teitge 8cf99f5200 Update german translations (#5419)
Signed-off-by: Roman Teitge <83205200+rteitge@users.noreply.github.com>
2026-01-04 19:10:08 +08:00
Steven 06d1c60aaf chore: tweak domain format 2026-01-03 20:43:10 +08:00
Johnny d2b421213f chore: optimize RelationList and unify RelationCard usage 2026-01-03 14:27:12 +08:00
Johnny 77e9376e03 chore: improve metadata section UI consistency and maintainability 2026-01-03 13:54:47 +08:00
Johnny 5612fb8f41 feat: add HDR image and video support
- Add HDR detection utilities for wide color gamut formats (HEIC, HEIF, WebP)
- Apply colorSpace attribute to image/video elements for HDR-capable files
- Update frontend components (AttachmentCard, PreviewImageDialog, AttachmentList)
- Expand backend thumbnail generation to support HEIC, HEIF, WebP formats
- Add Color-Gamut response headers to advertise wide gamut support
- Extend avatar MIME type validation for HDR formats

Supported formats:
- Images: HEIC, HEIF, WebP, PNG, JPEG
- Videos: MP4, QuickTime, Matroska, WebM (VP9 Profile 2)

Browser support:
- Safari 14.1+, Chrome 118+, Edge 118+
- Gracefully degrades to sRGB on unsupported browsers
2026-01-03 13:16:56 +08:00
Johnny e761ef8684 chore: move memo-metadata components to MemoView and MemoEditor
- Remove shared memo-metadata folder
- Move metadata display components (AttachmentList, LocationDisplay, RelationList) to MemoView/components/metadata
- Move attachment types and utilities (LocalFile, AttachmentItem, toAttachmentItems) to MemoEditor/types/attachment
- Simplify AttachmentList and AttachmentCard to work directly with Attachment proto
- Update all imports across MemoEditor and MemoView components
- Better separation of concerns: MemoView handles display, MemoEditor handles local files + attachments
2026-01-03 13:07:53 +08:00
Johnny a6e8ba7fb2 refactor: consolidate MemoEditor components (#5409) 2026-01-03 12:49:13 +08:00
Johnny a630b70ba9 chore: add .worktrees to gitignore 2026-01-03 12:44:37 +08:00
Guillaume e85a3da899 chore: add missing French locale translations (#5405)
Co-authored-by: Guillaume Reichenbach <guillaume.reichenbach@reflet-digital.com>
2026-01-03 07:46:24 +08:00
Lynchi 7b35a2672f chore: unify the Chinese localization of ellipsis (#5404)
Signed-off-by: Lynchi <77619755+Linqi1234@users.noreply.github.com>
2026-01-03 07:45:07 +08:00
Johnny d2acebcc53 fix: auth checks in reaction selector 2026-01-02 23:36:41 +08:00
Johnny ef8e3cfb99 chore: remove unused keyboard shortcuts 2026-01-02 09:57:09 +08:00
Johnny 02f39c2a59 refactor: replace generic LeafletMap with dedicated LocationPicker 2026-01-02 09:36:30 +08:00
Johnny f66c750075 chore: simplify attachment file writing 2025-12-31 21:54:37 +08:00
Johnny bd02de9895 chore: add store tests (#5397) 2025-12-31 21:26:35 +08:00
Johnny 12f32acd09 chore: remove dnd-kit dependencies 2025-12-31 09:32:23 +08:00
Johnny be1b758d30 refactor: simplify memo-metadata components 2025-12-31 09:27:37 +08:00
Johnny d7284fe867 refactor: nest reaction resource names under memos 2025-12-30 23:29:54 +08:00
Johnny c2aea5a4b7 feat: implement refresh token rotation with sliding window sessions in the auth service 2025-12-30 23:00:15 +08:00
Johnny d55af9b527 refactor: standardize loading indicators by using Spinner for route fallbacks and specializing Skeleton for memo lists 2025-12-30 21:54:22 +08:00
Johnny 61e94e8b08 refactor: replace i18n language change with loadLocale 2025-12-30 21:07:56 +08:00
Johnny 0735c11d75 feat: implement memo map in user profile 2025-12-30 20:41:44 +08:00
Johnny f416eb00b0 refactor(web): simplify Skeleton component structure 2025-12-30 08:58:01 +08:00
Johnny d7478b8003 perf: optimize memory usage for statistics and image processing 2025-12-30 00:06:23 +08:00
Johnny b826e90276 refactor: polish ActivityCalendar components with modern design 2025-12-29 23:40:35 +08:00
Johnny 5d677828a6 refactor: remove NSFW content settings from instance configuration 2025-12-29 20:13:54 +08:00
Johnny 96a91ebff0 chore: add week days to calendar 2025-12-29 08:59:08 +08:00
Johnny ea3371badb chore: add ActivityCalendar components 2025-12-28 19:59:36 +08:00
Johnny 78aa41336a feat: implement attachment filtering functionality 2025-12-28 18:47:59 +08:00
Johnny 955ff0cad6 refactor: optimize user fetching in MemoCommentMessage and MemoReactionListView components 2025-12-28 17:50:43 +08:00
Johnny 115d1bacd7 refactor: replace MemoSkeleton with a new Skeleton component for improved loading states 2025-12-28 17:31:21 +08:00
Johnny 792d58b74d refactor: consolidate and update type definitions across MemoEditor components 2025-12-28 13:17:02 +08:00
Johnny 40585607f4 refactor: streamline MemoView component and related hooks, removing unused code and integrating user data 2025-12-28 12:59:55 +08:00
Johnny 64ae13839a fix: add missing @types/hast dependency 2025-12-28 12:49:41 +08:00
Johnny 85f4fc7a75 refactor: remove MemoContentContext and integrate MemoViewContext
- Deleted MemoContentContext and its associated types.
- Updated Tag and TaskListItem components to use MemoViewContext instead.
- Refactored MemoContent component to eliminate context provider and directly use derived values.
- Simplified MemoViewContext to only include essential data.
- Enhanced error handling in various components by introducing a centralized error handling utility.
- Improved type safety across components and hooks by refining TypeScript definitions.
- Updated remark plugins to enhance tag parsing and preserve node types.
2025-12-28 12:46:12 +08:00
Johnny ab650ac86d chore: remove unused dependency react-simple-pull-to-refresh from lockfile 2025-12-27 10:26:27 +08:00
Johnny d711d724bb chore: clean up unused imports and parameters across components 2025-12-27 10:18:38 +08:00
Johnny 0ad75b8f08 refactor: replace useResponsiveWidth with useMediaQuery across components 2025-12-26 23:44:52 +08:00
boojack d21610cce1 chore: add @johnnyjoygh as a code owner
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-12-26 23:04:16 +08:00
Steven 12fdf930a6 fix: invalidate React Query cache after memo reaction changes 2025-12-26 00:13:44 +08:00
Steven 9f5a7bb889 docs: create AGENTS.md for AI agents and remove outdated CLAUDE.md
- Remove outdated CLAUDE.md with obsolete architecture references
- Create comprehensive AGENTS.md covering:
  - Backend: Go, gRPC, Connect RPC, store layer, migrations
  - Frontend: React, React Query, Context API, state management
  - Development commands, workflows, and testing patterns
  - Code conventions, configuration, CI/CD, and security notes
2025-12-25 23:48:16 +08:00
Steven 6523891982 fix: react hooks order violation in MemoDetail when creating comments
Replace dynamic hook mapping with useMemoComments hook to fetch all comments
via listMemoComments API, ensuring consistent hook order across renders and
fixing page load failure after comment creation.
2025-12-25 23:40:42 +08:00
Steven c4dfb85400 fix: ensure dispatch is used for actions in useMemoInit hook 2025-12-25 23:17:34 +08:00
Steven 28e4ade009 fix: register Catalan and Galician locales in i18n configuration
The translation files ca.json and gl.json existed but weren't registered in the locales array, preventing users from selecting these languages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:52:51 +08:00
Steven d4e08ae2bd refactor(react-query): optimize config, add error boundary, and remove JSDoc
This commit combines multiple improvements to the React Query migration:

Performance Optimization:
- Increase default staleTime from 10s to 30s for better performance
- Reduces unnecessary network requests while maintaining data freshness

Error Handling:
- Add ErrorBoundary component with user-friendly error UI
- Integrated at app root level for comprehensive coverage
- Provides error details and reload option

Documentation:
- Add docs/auth-architecture.md explaining AuthContext design decisions
- Document why AuthContext is preferred over React Query for current user

Code Cleanup:
- Remove all JSDoc comments from hooks and components
- Keep essential inline comments for clarity
- Simplifies code readability

Files modified:
- src/lib/query-client.ts - Optimized staleTime
- src/main.tsx - Added ErrorBoundary wrapper
- src/components/ErrorBoundary.tsx - New component
- src/hooks/useMemoQueries.ts - Removed JSDoc
- src/hooks/useUserQueries.ts - Removed JSDoc
- src/components/PagedMemoList/PagedMemoList.tsx - Removed JSDoc
- docs/auth-architecture.md - New documentation

All changes verified with TypeScript compilation and production build.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:47:36 +08:00
ghose eed935ce44 feat: contribution New Locale: Galician (gl, gl_ES) (#5376)
Signed-off-by: ghose <704948+xmgz@users.noreply.github.com>
2025-12-25 08:38:24 +08:00
dwojtas 9821d6ace4 chore: add missing keys to Polish translation, based on the en.json file (#5380) 2025-12-25 08:37:14 +08:00
Steven b2e2b6426c perf(react-query): fix context re-renders and improve type safety
Optimizes React Query migration with performance and consistency improvements:

Performance:
- Memoize AuthContext and InstanceContext provider values to prevent unnecessary re-renders
- Convert InstanceContext getter functions to useMemo hooks
- Fix refetchSettings to avoid state dependency that caused frequent recreations

Type Safety:
- Replace 'any' types in useAttachmentQueries with proper protobuf types
- Add Attachment and ListAttachmentsRequest type imports

Query Key Consistency:
- Replace hardcoded ["users", "stats"] with userKeys.stats() factory function
- Ensures consistent cache key management across mutations

Developer Experience:
- Rename unused useCurrentUser to useCurrentUserQuery to avoid confusion
- Add documentation explaining AuthContext-based vs React Query current user hooks
- Update internal references in useNotifications and useTagCounts

All changes verified with TypeScript compilation and build tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 08:29:34 +08:00
Johnny f87f728b0f feat: react query migration (#5379) 2025-12-24 22:59:18 +08:00
Johnny 4109fe3245 chore(MemoEditor): enhance focus mode handling and improve editor layout 2025-12-23 20:11:38 +08:00
Johnny 595daaa163 style: organize imports in MemoView hooks 2025-12-23 19:33:31 +08:00
Johnny 0f9322ea11 fix(MemoEditor): dispatch toggleFocusMode action properly
- Wrap actions.toggleFocusMode() with dispatch() call
- Create toggleFocusMode helper function for callbacks
- Fix focus mode not toggling due to action not being dispatched
2025-12-23 19:30:38 +08:00
Johnny 201a0466e9 fix(MemoEditor): restore focus mode functionality
- Add useFocusMode hook to lock body scroll in focus mode
- Add 'f' key keyboard shortcut to toggle focus mode
- Add FocusModeExitButton inside editor
- Import and wire up all focus mode components and hooks
- Update useKeyboard to handle focus mode toggle
2025-12-23 19:20:21 +08:00
Johnny ca84241b8a fix(MemoEditor): restore focus mode styles
- Import and use FOCUS_MODE_STYLES from constants
- Apply proper fixed positioning, shadow, and spacing in focus mode
- Add transition animation for smooth mode switching
- Replace empty 'focus-mode' class with actual Tailwind utilities
2025-12-23 19:18:24 +08:00
Johnny f2bc115a1d fix(MemoEditor): restore wrapper styles removed by refactoring
- Add back Tailwind utility classes for proper layout
- Restore padding, border, background, and flex styles
- Fix missing styles on memo-editor-wrapper element
2025-12-23 19:17:00 +08:00
Johnny 735dd1fe4b style(MemoView): restore comments and formatting
- Add back descriptive comments removed by editor refactoring commit
- Restore original timestamp calculation format in MemoHeader
- Improve code readability with section comments
2025-12-23 19:05:29 +08:00
Johnny e61d594ded refactor(MemoView): improve maintainability and code organization
Complete refactoring of MemoView components for better code quality:

- Split useMemoViewState into individual hook files (useMemoActions,
  useKeyboardShortcuts, useNsfwContent, useImagePreview, useMemoCreator)
  for single responsibility principle
- Consolidate types closer to usage - move hook-specific types to
  respective files, keep only component props in shared types.ts
- Optimize context with separate static/dynamic memoization to reduce
  unnecessary re-renders
- Simplify barrel exports to only expose public API (MemoView component
  and MemoViewProps type)
- Add comprehensive JSDoc documentation to all public APIs with usage
  examples

Benefits:
- Better maintainability: each hook file has one clear purpose
- Improved performance: context optimization prevents unnecessary re-renders
- Enhanced developer experience: clear documentation and encapsulation
- Cleaner architecture: public API is minimal, internal details hidden

All automated checks pass (TypeScript compilation, linter, production build).
2025-12-23 19:01:57 +08:00
Johnny 1b11e8c841 refactor(editor): complete state machine and services migration
BREAKING CHANGE: MemoEditor internal architecture completely refactored

## Summary

Refactored MemoEditor from hooks-based state management to a three-layer
architecture (Presentation → State → Services) using useReducer pattern.

## Changes

### Architecture
- **State Layer** (5 new files): types, actions, reducer, context, barrel export
- **Service Layer** (6 new files): error, validation, upload, cache, memo services + barrel
- **Component Layer** (3 new files): EditorToolbar, EditorContent, EditorMetadata
- **Simplified Hooks** (3 new files): useMemoInit, useAutoSave, useKeyboard

### Code Reduction
- Main component: ~380 lines → ~140 lines (-63%)
- Hooks removed: 5 old hooks (useMemoEditorState, useMemoSave, etc.)
- Total lines removed: 508 lines of old code
- Utility hooks preserved: 8 hooks still in use (useLocation, useDragAndDrop, etc.)

### Improvements
-  Predictable state transitions with useReducer
-  Testable business logic in pure service functions
-  Cleaner component code (presentation only)
-  Better separation of concerns
-  Type-safe actions with discriminated unions
-  Centralized error handling

## Statistics
- Files changed: 26
- Commits created: 25 (squashed into 1)
- New files: 17
- Removed files: 5
- TypeScript errors: 0
- Lint errors: 0

## Testing
Manual testing required for:
- Editor functionality (create, edit, save)
- Drag and drop
- Focus mode
- Keyboard shortcuts (Cmd/Ctrl + Enter)
- Auto-save to localStorage
2025-12-23 08:38:02 +08:00
Johnny 8a7c976758 refactor: streamline tag sorting and update coordinate handling in MemoEditor components 2025-12-22 22:54:09 +08:00
Johnny d537591005 feat: add slash commands tooltip to InsertMenu 2025-12-22 22:42:23 +08:00
Steven f9dd7ad853 style: improve code block styling and formatting
- Adjust CodeBlock styling for better layout and spacing
- Reorganize copy button positioning with absolute positioning
- Simplify button styling and reduce icon sizes
- Wrap MermaidBlock in pre tag for consistent structure
- Format useDropdownMenuSubHoverDelay hook call for readability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 21:27:50 +08:00
Steven dfc0d376d1 refactor: extract submenu hover delay logic into reusable hook
- Create useDropdownMenuSubHoverDelay hook in dropdown-menu component
- Encapsulates hover delay behavior for preventing accidental submenu closure
- Eliminates code duplication at component usage sites
- Simplifies InsertMenu by removing 45 lines of timeout/state management code
- Hook provides handleTriggerEnter/Leave and handleContentEnter/Leave handlers
- Configurable closeDelay parameter (default 150ms)

This makes the hover behavior pattern reusable across any dropdown menu submenus.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 21:04:00 +08:00
Steven 332d32bd35 fix: render dates correctly in memo detail sidebar and link dialog
Convert protobuf Timestamp objects to Date before formatting
to prevent "[object Object]" from appearing in the UI.

Fixes #5368
2025-12-22 20:24:04 +08:00
Steven be7ef74698 fix: eliminate duplicate API requests by deduplicating user fetch calls
- Add request deduplication to getOrFetchUser using RequestDeduplicator
- Consolidates multiple simultaneous calls for same user into single API request
- Prevents duplicate 401 errors and wasted network traffic
- Matches pattern already used by fetchUsers and fetchUserStats
- Remove backwards compatibility aliases (getOrFetchUserByName, getOrFetchUserByUsername)
- Update all call sites to use canonical getOrFetchUser method

Fixes issue where PagedMemoList, useMemoViewState, MainLayout, and UserProfile
were making duplicate user fetch requests when loading user data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 20:12:44 +08:00
Johnny 5828f34aae feat: implement scheduler plugin
- Added `scheduler` package with core functionalities for job scheduling.
- Implemented job registration, execution, and graceful shutdown mechanisms.
- Introduced middleware support for logging, recovery from panics, and timeout handling.
- Developed cron expression parser to support both 5-field and 6-field formats.
- Created comprehensive integration and unit tests for scheduler, job definitions, middleware, and parser functionalities.
- Enhanced logging capabilities to track job execution and errors.
2025-12-20 15:43:25 +08:00
Johnny b55a0314f8 feat: add Email Plugin with SMTP functionality
- Implemented the Email Plugin for self-hosted Memos instances, providing SMTP email sending capabilities.
- Created configuration structure for SMTP settings with validation.
- Developed message structure for email content with validation and formatting.
- Added synchronous and asynchronous email sending methods.
- Implemented error handling and logging for email sending processes.
- Included tests for client, configuration, and message functionalities to ensure reliability.
- Updated documentation to reflect new features and usage instructions.
2025-12-20 14:23:15 +08:00
Johnny 319a7cac94 chore: fix remark tag parse 2025-12-20 13:50:32 +08:00
Johnny 6b0f90f355 chore: prevent sensitive data caching 2025-12-20 12:33:16 +08:00
Johnny eaef04a0a0 chore: fix linter 2025-12-20 11:55:00 +08:00
Steven d236ef1611 feat(web): add glassmorphism map controls with Google Maps integration
- Add custom zoom controls with modern glassmorphism styling
- Add "Open in Google Maps" button for location markers
- Refactor to React component architecture with proper Leaflet integration
- Create reusable GlassButton component for maintainability
- Use React 18 createRoot for portal rendering
- Replace imperative DOM manipulation with declarative React patterns
- Add coordinate display to location metadata

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-20 00:18:01 +08:00
Steven d0c3908168 refactor: remove deprecated Sessions and AccessTokens settings
- Remove ListSessions and RevokeSession RPC endpoints
- Remove Session message and SessionsSetting from UserSetting
- Remove ACCESS_TOKENS key and AccessTokensSetting
- Update references to use RefreshTokensUserSetting with its own ClientInfo
- Remove UserSessionsSection frontend component
- Clean up user store to remove session and access token settings
- Regenerate protobuf files

The system now uses:
- REFRESH_TOKENS for session management with sliding expiration
- PERSONAL_ACCESS_TOKENS for long-lived API tokens
2025-12-19 08:35:57 +08:00
Steven a6c32908a0 refactor(auth): remove legacy session cookie authentication
- Remove SessionCookieName and SessionSlidingDuration constants
- Remove ExtractSessionCookieFromHeader() function
- Remove SessionIDContextKey and GetSessionID() function
- Remove sessionID parameter from SetUserInContext()
- Remove SessionID field from AuthResult struct
- Remove session cookie extraction from middleware
- Update documentation to reflect JWT + PAT only auth

Session cookies were never being set since migration to refresh token
authentication. This change removes ~50 lines of dead code and clarifies
that the system uses JWT access tokens, refresh tokens, and PATs only.
2025-12-19 00:09:08 +08:00
Steven b0aeb06f85 refactor(web): improve auth flow and eliminate route duplication
- Extract route paths to router/routes.ts as single source of truth
- Refactor connect.ts auth interceptor with better structure and error handling
  - Add TokenRefreshManager class to prevent race conditions
  - Implement smart redirect logic for public/private routes
  - Support unauthenticated access to explore and user profile pages
  - Add proper error handling for missing access tokens
  - Extract magic strings to named constants
- Maintain backward compatibility by aliasing Routes to ROUTES

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 22:14:30 +08:00
Johnny 50606a850e fix(auth): resolve token refresh and persistence issues
- Fix cookie expiration timezone to use GMT (RFC 6265 compliance)
- Use Connect RPC client for token refresh instead of fetch
- Fix error code checking (numeric Code.Unauthenticated instead of string)
- Prevent infinite redirect loop when already on /auth page
- Fix protobuf Timestamp conversion using timestampDate helper
- Store access token in sessionStorage to avoid unnecessary refreshes on page reload
- Add refresh token cookie fallback for attachment authentication
- Improve error handling with proper type checking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 20:56:54 +08:00
Johnny 7932f6d0d0 refactor: user auth improvements (#5360) 2025-12-18 18:15:51 +08:00
Johnny 2c2ef53737 chore: fix frontend linter 2025-12-17 09:04:05 +08:00
Johnny ea14280cb3 feat: enhance attachment handling with MIME type validation 2025-12-17 08:58:43 +08:00
Johnny 642271a831 feat: add iframe support for embedded videos in markdown content 2025-12-17 08:52:59 +08:00
Johnny 310590b278 chore: fix golang checks 2025-12-16 22:53:36 +08:00
Johnny 40e129b8af refactor(auth): streamline session authentication and cookie handling 2025-12-16 22:23:59 +08:00
Steven 87b8c2b2d2 refactor(web): rename grpcweb.ts to connect.ts and enable binary format
- Rename grpcweb.ts to connect.ts to reflect ConnectRPC usage
- Enable binary protobuf format for improved performance
- Update all imports across 26 files from @/grpcweb to @/connect

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 20:15:16 +08:00
Steven 6926764b91 fix: allow unauthenticated CreateUser for first user registration
Add CreateUser to PublicMethods ACL whitelist to fix "authentication required"
error during first-time setup. The CreateUser method already has proper security
logic that automatically assigns HOST role to the first user and enforces
DisallowUserRegistration setting for subsequent users.

Fixes #5352

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 23:18:30 +08:00
Steven b1a52f20ed fix(web): add clipboard fallback for CodeBlock copy button in non-secure contexts
The CodeBlock component was refactored in v0.25.3 to use navigator.clipboard.writeText(),
which requires HTTPS or localhost. This caused the copy button to fail silently for users
accessing Memos over HTTP.

This fix adds a fallback to the copy-to-clipboard library (already used by all other
copy operations in the codebase) when the native clipboard API is unavailable or fails,
ensuring the copy button works reliably in all deployment scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 22:51:34 +08:00
Steven a2ddf05933 chore: fix linter 2025-12-15 19:58:58 +08:00
Steven 1b3318f886 refactor(web): improve ActivityCalendar maintainability and add Calendar page
- Extract shared utilities and constants to eliminate code duplication
- Create dedicated Calendar page with year view and month grid
- Add date filter navigation with bidirectional URL sync
- Fix useTodayDate memoization bug causing stale date references
- Standardize naming conventions (get vs generate functions)
- Add comprehensive type exports and proper store encapsulation
- Implement size variants for compact calendar display

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 19:47:46 +08:00
Johnny d14e66daf5 fix: openapi generation (#5349) 2025-12-15 10:55:04 +08:00
Davide Truffa 8659f69da0 chore(locales): update Italian translation (#5346) 2025-12-15 10:05:32 +08:00
Johnny 09afa579e4 chore: implement session sliding expiration and JWT authentication
- Added UpdateSessionLastAccessed method to update session access time.
- Enhanced Authenticate method to support both session cookie and JWT token authentication.
- Introduced AuthResult struct to encapsulate authentication results.
- Added SetUserInContext function to simplify context management for authenticated users.

refactor(auth): streamline gRPC and HTTP authentication

- Removed gRPC authentication interceptor and replaced it with a unified approach using GatewayAuthMiddleware for HTTP requests.
- Updated Connect interceptors to utilize the new authentication logic.
- Consolidated public and admin-only method checks into service layer for better maintainability.

chore(api): clean up unused code and improve documentation

- Removed deprecated logger interceptor and unused gRPC server code.
- Updated ACL configuration documentation for clarity on public and admin-only methods.
- Enhanced metadata handling in Connect RPC to ensure consistent header access.

fix(server): simplify server startup and shutdown process

- Eliminated cmux dependency for handling HTTP and gRPC traffic.
- Streamlined server initialization and shutdown logic for better performance and readability.
2025-12-15 10:04:11 +08:00
Steven 65a19df4be fix(backend): correct generic type parameter in withHeaderCarrier helper
Problem:
The withHeaderCarrier generic function had a type mismatch that caused compilation
errors in CI. The function used `T proto.Message` constraint, but Connect's Response
type expects the non-pointer message type while protobuf methods return pointers.

Error from CI:
  type T of resp does not match *T (cannot infer T)

This occurred because:
- Connect methods expect: *connect.Response[v1pb.CreateSessionResponse]
- Service methods return: (*v1pb.CreateSessionResponse, error)
- Old signature: fn func(context.Context) (T, error) with T proto.Message
- This caused T to be inferred as *v1pb.CreateSessionResponse
- Leading to return type: *connect.Response[*v1pb.CreateSessionResponse] (wrong!)

Solution:
Changed generic signature to explicitly handle the pointer/non-pointer distinction:
- New signature: fn func(context.Context) (*T, error) with T any
- T is now the non-pointer type (e.g., v1pb.CreateSessionResponse)
- fn returns *T (e.g., *v1pb.CreateSessionResponse)
- Return type is correctly: *connect.Response[T] (e.g., *connect.Response[v1pb.CreateSessionResponse])

Also removed unused "google.golang.org/protobuf/proto" import and improved documentation
to clarify the T vs *T distinction.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 08:06:13 +08:00
Steven 06a0f8d618 fix(web): convert visibility enum values to string names in filter expressions
Problem:
The Explore page filter was sending visibility filter as:
  visibility in ["3", "2"]
when it should send:
  visibility in ["PUBLIC", "PROTECTED"]

The backend CEL filter parser expects string enum names, not numeric values.
This caused the Explore page to return no memos even when public memos existed.

Solution:
- Added getVisibilityName() helper to convert Visibility enum values to string names
- Updated useMemoFilters to use getVisibilityName() when building visibility filter
- Follows same pattern as existing getInstanceSettingKeyName() and getUserSettingKeyName()
- Added validation to warn on invalid enum values

Files changed:
- web/src/store/common.ts: Add getVisibilityName() helper with validation
- web/src/hooks/useMemoFilters.ts: Use getVisibilityName() in visibility filter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 08:03:25 +08:00
Steven 3d893a7394 fix(backend): implement protocol-agnostic header setting for dual gRPC/Connect-RPC support
Problem:
The codebase supports both native gRPC and Connect-RPC protocols, but auth
service was using grpc.SetHeader() which only works for native gRPC. This
caused "failed to set grpc header" errors when using Connect-RPC clients
(browsers using nice-grpc-web).

Solution:
- Created HeaderCarrier pattern for protocol-agnostic header setting
- HeaderCarrier stores headers in context for Connect-RPC requests
- Falls back to grpc.SetHeader for native gRPC requests
- Updated auth service to use SetResponseHeader() instead of grpc.SetHeader()
- Refactored Connect wrappers to use withHeaderCarrier() helper to eliminate
  code duplication

Additional fixes:
- Allow public methods when gRPC metadata is missing in ACL interceptor
- Properly handle ParseSessionCookieValue errors instead of ignoring them
- Fix buildSessionCookie to gracefully handle missing metadata

Files changed:
- server/router/api/v1/header_carrier.go: New protocol-agnostic header carrier
- server/router/api/v1/auth_service.go: Use SetResponseHeader, handle missing metadata
- server/router/api/v1/connect_services.go: Use withHeaderCarrier helper
- server/router/api/v1/acl.go: Allow public methods without metadata
- server/router/api/v1/connect_interceptors.go: Handle ParseSessionCookieValue errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 07:46:28 +08:00
Steven 8a7e00886d fix(web): convert enum values to string names in API resource paths
Frontend was incorrectly using numeric enum values (e.g., 1, 2, 3) instead
of string names (e.g., "GENERAL", "STORAGE") when constructing API resource
paths. This caused the backend to fail with "unsupported instance setting
key: INSTANCE_SETTING_KEY_UNSPECIFIED" errors during initialization.

Changes:
- Add helper functions in store/common.ts to convert enum values to names
  - getInstanceSettingKeyName() and buildInstanceSettingName()
  - getUserSettingKeyName() and buildUserSettingName()
- Update instance store to use string enum names in API calls
- Update user store to use string enum names in API calls
- Update all components to use new helper functions for setting names

Fixes enum string conversion for:
- InstanceSetting_Key (6 locations)
- UserSetting_Key (2 locations)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 20:08:11 +08:00
Johnny edd3ced9bf refactor: migrate to connect-rpc (#5338) 2025-12-11 19:49:07 +08:00
Steven 8af8b9d238 fix(web): use AST parsing for task detection to handle code blocks correctly
Fixes #5319. Checkboxes inside code blocks were incorrectly counted when
toggling tasks, causing the wrong checkbox to be checked. Replaced regex-based
task detection with mdast AST parsing which properly ignores code block content.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 08:26:16 +08:00
Steven 3dc740c752 refactor(web): improve locale/theme preference initialization
- Extract preference logic into dedicated hooks (useUserLocale, useUserTheme)
- Add applyLocaleEarly() for consistent early application
- Remove applyUserPreferences() from user store (now redundant)
- Simplify App.tsx by moving effects to custom hooks
- Make locale/theme handling consistent and reactive
- Clean up manual preference calls from sign-in flows

Fixes locale not overriding localStorage on user login.
Improves maintainability with better separation of concerns.
2025-12-11 07:59:52 +08:00
spaghetti-coder 7479205e21 fix(ui): change focus search bar shortcut overlapping with url shortcut (#5336) 2025-12-11 07:56:20 +08:00
XIN_____ baf33af980 chore: add 'all' translation to zh-Hans and zh-Hant (#5333) 2025-12-11 07:53:20 +08:00
Shivam Kumar 41358ed3ba fix(theme): improve text contrast in default dark mode (#5323)
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2025-12-11 07:53:02 +08:00
xiaolinny 6beb3fcde0 chore: fix some typos in comments (#5332)
Signed-off-by: xiaolinny <xiaolincode@outlook.com>
2025-12-11 07:50:16 +08:00
Steven 48ce4ccc26 fix(web): disable setext header syntax (#5314)
Add custom remark plugin to prevent setext headers (headers using === or --- underlines) from being recognized by the markdown parser. The plugin disables the setextUnderline construct at the micromark parser level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 09:07:54 +08:00
Steven 1cf047707b refactor: migrate binary file serving from gRPC to dedicated HTTP fileserver
Migrates attachment and avatar binary serving from gRPC endpoints to a new dedicated HTTP fileserver package, fixing Safari video playback issues and improving architectural separation.

Key changes:
- Created server/router/fileserver package for all binary file serving
- Removed GetAttachmentBinary and GetUserAvatar gRPC endpoints from proto
- Implemented native HTTP handlers with full range request support
- Added authentication support (session cookies + JWT) to fileserver
- New avatar endpoint supports lookup by user ID or username
- Eliminated duplicate auth constants (imports from api/v1)

HTTP endpoints:
- Attachments: /file/attachments/:uid/:filename (unchanged URL)
- Avatars: /file/users/:identifier/avatar (new URL format)

This fixes Safari video/audio playback by using http.ServeContent() which properly handles HTTP 206 Partial Content responses and range request headers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-09 08:53:52 +08:00
spaghetti-coder 9ea27ee61f fix(ui): fix todo command does nothing (#5329) 2025-12-09 08:20:57 +08:00
spaghetti-coder 618db89f4f fix(ui): remove unsupported highlight command (#5328) 2025-12-09 07:57:28 +08:00
XIN_____ 2a876436e0 chore: add 'auto-expand' translation in zh-Hans.json (#5326) 2025-12-08 21:03:57 +08:00
Steven 4668c4714b refactor(web): improve MemoContent security and maintainability
Security improvements:
- Add rehype-sanitize for XSS protection in markdown content
- Remove DOMPurify and deprecated __html code block feature
- Extract sanitize schema to constants with comprehensive documentation

Maintainability improvements:
- Extract SANITIZE_SCHEMA to constants.ts for better organization
- Create utils.ts with shared code extraction utilities
- Refactor CodeBlock and MermaidBlock to use shared utilities
- Rename PreProps to CodeBlockProps for clarity
- Reduce code duplication across components

Dependency cleanup:
- Remove explicit katex dependency (now transitive via rehype-katex)
- Remove @matejmazur/react-katex (unused)
- Remove dompurify (replaced by rehype-sanitize)
- Update vite config to remove katex-vendor chunk

Changes: 7 files changed, 84 insertions(+), 100 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:45:22 +08:00
Steven d9f8bc80f0 feat(web): add LaTeX math rendering support to MemoContent
Integrates remark-math and rehype-katex plugins to enable LaTeX mathematical expressions in memos. Users can now write inline math ($...$) and display math ($$...$$) using standard LaTeX syntax.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:08:45 +08:00
Steven 81da20c905 refactor: simplify theme/locale to user preferences and improve initialization
Remove theme and locale from instance settings to eliminate duplication and
simplify the codebase. These are user-specific preferences and should only
exist in user settings, not instance-wide settings.

Backend changes:
- Remove theme from InstanceGeneralSetting proto
- Remove locale from InstanceCustomProfile proto
- Update instance service converters to remove theme/locale handling
- Simplify RSS feed to use static locale

Frontend changes:
- Remove theme/locale from instanceStore state
- Create unified initialization flow with clear fallback priority:
  * Theme: user setting → localStorage → system preference
  * Locale: user setting → browser language
- Add applyUserPreferences() to centralize theme/locale application
- Simplify App.tsx by removing redundant state synchronization
- Update all components to use new helper functions:
  * getThemeWithFallback() for theme resolution
  * getLocaleWithFallback() for locale resolution
- Remove theme/locale selectors from instance profile dialog

Theme utilities refactor:
- Organize code into clear sections with JSDoc comments
- Extract localStorage operations into getStoredTheme/setStoredTheme helpers
- Split DOM manipulation into focused functions
- Improve type safety with Theme and ResolvedTheme types
- Reduce code duplication and improve maintainability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 09:08:46 +08:00
Steven 8154a411a9 fix(web): allow only one active tag filter at a time
Previously, clicking multiple tags would add them all as active filters. Now clicking a new tag automatically clears any existing tag filters before applying the new one, ensuring only one tag can be filtered at a time. Clicking an already-active tag still deselects it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 08:40:43 +08:00
Johnny a863154224 docs: update Memos Codebase Guide for clarity and structure 2025-12-02 08:19:20 +08:00
Steven 0610257562 refactor(store): remove deprecated migration_history table and backward compatibility code
Complete removal of migration_history system in favor of instance_setting based schema versioning.

Changes:
- Remove migration_history table creation from all LATEST.sql files
- Delete all migration_history model and implementation files (~300 lines)
- Remove FindMigrationHistoryList and UpsertMigrationHistory from Driver interface
- Replace complex backward compatibility functions with simple version check
- Update health check to use instance_setting instead of migration_history
- Simplify checkMinimumUpgradeVersion to detect pre-v0.22 installations

Breaking change:
Users on versions < v0.22.0 (May 2024) must upgrade to v0.25.x first before upgrading to this version.
Clear error message with upgrade instructions will be shown for old installations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 22:54:30 +08:00
Steven fae5eac31b fix(web): fix infinite loop in MemoEditor and improve React/MobX integration
- Wrap all setter functions in useMemoEditorState with useCallback to ensure stable references
  This prevents infinite loops when setters are used in useEffect dependencies (fixes "Maximum update depth exceeded" error)
- Extract MobX observable values in useMemoFilters and useMemoSorting before using them in useMemo dependencies
  This prevents React from tracking MobX observables directly, improving reliability
- Add comprehensive documentation explaining the design decisions for future maintainability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:54:40 +08:00
Steven d1492007ab fix(store): filter inbox notifications by message type at database level
Add MessageType filter to FindInbox to exclude legacy VERSION_UPDATE
notifications from inbox queries. This resolves the issue where users
saw notification counts but no items displayed, as VERSION_UPDATE
entries cannot be rendered in the new UserNotification API.

Changes:
- Add MessageType field to FindInbox struct for database-level filtering
- Implement JSON extraction filters in SQLite, MySQL, and PostgreSQL drivers
- Update ListUserNotifications to filter MEMO_COMMENT type at store level

This approach improves performance by filtering at the database rather
than in application code, reducing unnecessary data transfer for users
with many legacy inbox entries.

Fixes #5278

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:43:05 +08:00
Steven 17e116b977 chore: fix linter 2025-12-01 08:27:23 +08:00
Johnny 545323d12c refactor(rss): comprehensive RSS service improvements
Major performance and standards compliance improvements to RSS feed generation:

Performance optimizations:
- Fix N+1 query problem by batch loading attachments (101 queries → 2-3)
- Add in-memory caching with 1-hour TTL and LRU eviction
- Implement ETag-based conditional requests (304 Not Modified)
- Add database-level pagination with LIMIT clause
- Clean up expired cache entries to prevent memory leaks

RSS 2.0 compliance:
- Add item titles extracted from memo content
- Include both description and content:encoded fields
- Add author information (name and email)
- Set proper Last-Modified headers
- Use specific application/rss+xml content type

Code quality:
- Fix potential index out of bounds panic in title generation
- Improve markdown heading stripping with regex (handles # to ######)
- Add proper HTTP caching headers (Cache-Control, ETag, Last-Modified)
- Thread-safe cache implementation with RWMutex
- Better error handling and edge case coverage

The RSS backend now follows industry best practices with optimal
performance, full standards compliance, and production-ready reliability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 00:28:23 +08:00
Johnny 1a9bd32cf1 feat(auth): add PKCE support and enhance OAuth security
Implements critical OAuth 2.0 security improvements to protect against authorization code interception attacks and improve provider compatibility:

- Add PKCE (RFC 7636) support with SHA-256 code challenge/verifier
- Fix access token extraction to use standard field instead of Extra()
- Add OAuth error parameter handling (access_denied, invalid_scope, etc.)
- Maintain backward compatibility for non-PKCE flows

This brings the OAuth implementation up to modern security standards as recommended by Auth0, Okta, and the OAuth 2.0 Security Best Current Practice (RFC 8252).

Backend changes:
- Add code_verifier parameter to ExchangeToken with PKCE support
- Use token.AccessToken for better provider compatibility
- Update proto definition with optional code_verifier field

Frontend changes:
- Generate cryptographically secure PKCE parameters
- Include code_challenge in authorization requests
- Handle and display OAuth provider errors gracefully
- Pass code_verifier during token exchange

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 00:04:26 +08:00
Johnny a6a8997f4c chore: tweak comments 2025-11-30 13:16:02 +08:00
Johnny 07072b75a7 chore: reorganize reaction components 2025-11-30 12:48:21 +08:00
Johnny 6dcf7cc74c chore: enhance MemoView component structure 2025-11-30 12:41:24 +08:00
Johnny 7aa8262ef2 chore: streamline MemoEditor components and remove unused code 2025-11-30 12:30:00 +08:00
Huang Youchuan 26cb357685 fix: update user session retrieval to use user.ID instead of userID (#5294)
Co-authored-by: huangyouchuan <huangyouchuan@letu.com>
2025-11-30 11:45:16 +08:00
Johnny ee9d9603ee chore: remove goreleaser 2025-11-30 11:42:46 +08:00
Johnny 2516cdf2b4 refactor: clean up MemoView and MemoEditor component architecture
This commit refactors MemoView and MemoEditor components for better
maintainability, introducing React Context, custom hooks, and improved
folder structure.

MemoView improvements:
- Introduce MemoViewContext to eliminate prop drilling
- Reduce MemoHeader props from 18 to 8
- Reduce MemoBody props from 9 to 4
- Extract custom hooks: useMemoViewDerivedState, useMemoEditor,
  useMemoHandlers for better separation of concerns
- Fix React hooks ordering bug in edit mode

MemoEditor improvements:
- Extract state management into useMemoEditorState hook
- Extract keyboard handling into useMemoEditorKeyboard hook
- Extract event handlers into useMemoEditorHandlers hook
- Extract initialization logic into useMemoEditorInit hook
- Reduce main component from 461 to 317 lines (31% reduction)

Folder structure cleanup:
- Move SortableItem to memo-metadata (correct location)
- Move ErrorBoundary to components folder
- Flatten Toolbar/InsertMenu structure (remove unnecessary nesting)
- Consolidate hooks in main hooks folder
- Consolidate types in main types folder

Benefits:
- Better separation of concerns
- Improved testability
- Easier maintenance
- Cleaner code organization
- No functionality changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 11:15:20 +08:00
Johnny bb7e0cdb79 refactor: remove enable link preview setting
- Remove enable_link_preview field from proto definitions
- Remove setting UI from MemoRelatedSettings component
- Remove translations from all 33 locale files
- Regenerate proto files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:34:22 +08:00
Johnny 5fb6f8eccf refactor: remove legacy disable markdown shortcuts setting
- Remove disable_markdown_shortcuts field from proto definitions
- Remove setting UI from MemoRelatedSettings component
- Enable markdown shortcuts permanently in MemoEditor
- Remove translations from all 32 locale files
- Fix TypeScript error in useMemoSave hook by using typed translation function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:30:55 +08:00
Johnny 2b7b70ebfe chore: fix linter 2025-11-30 10:15:20 +08:00
Johnny 1ef11f7470 refactor: implement MemoView component with subcomponents and hooks
- Added MemoView component to display a single memo card with full functionality including creator info, memo content, attachments, reactions, and comments.
- Created MemoBody and MemoHeader subcomponents to separate concerns and improve maintainability.
- Introduced custom hooks for managing memo actions, keyboard shortcuts, NSFW content visibility, and image preview.
- Implemented reaction handling with new ReactionSelector and ReactionView components.
- Added TypeScript types for better type safety and clarity.
- Established constants for memo card styling and keyboard shortcuts.
- Removed legacy ReactionSelector and ReactionView components from the previous structure.
2025-11-29 23:21:35 +08:00
Johnny 50199fe998 feat: add LocationDialog and related hooks for location management in MemoEditor
- Implemented LocationDialog component for selecting and entering location coordinates.
- Created useLocation hook to manage location state and updates.
- Added LocationState type for managing location data.
- Introduced useLinkMemo hook for linking memos with search functionality.
- Added VisibilitySelector component for selecting memo visibility.
- Refactored MemoEditor to integrate new hooks and components for improved functionality.
- Removed obsolete handlers and streamlined memo save logic with useMemoSave hook.
- Enhanced focus mode functionality with dedicated components for overlay and exit button.
2025-11-28 09:21:53 +08:00
Chriss c1765fc246 feat: add midnight theme (#5288) 2025-11-27 21:21:57 +08:00
Steven 07a030ddfd fix(postgres): update tag filtering SQL to ensure proper type casting for LIKE comparisons 2025-11-26 23:04:07 +08:00
Steven 50f49fc00d chore: update demo data 2025-11-26 21:58:56 +08:00
Steven 05f7c9606b fix: add HTML sanitization and dynamic theme loading 2025-11-26 20:34:52 +08:00
Steven 363bc9f455 fix(web): add missing tag styles and unify primary color across themes
Tags were missing CSS styles, appearing as plain text. Added text-primary
styling to Tag component and updated default theme primary color to match
other themes (blue hue 250, chroma 0.08) for consistency.

Fixes #5282

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:25:28 +08:00
Steven 5a16f8009f fix(markdown): render single newlines as line breaks
Add remark-breaks plugin to render single newlines as <br> tags,
matching GitHub Flavored Markdown behavior.

Fixes https://github.com/usememos/memos/issues/5277

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:13:57 +08:00
김강현 ef033d21de chore(i18n): add missing Korean translations (#5285) 2025-11-26 20:02:57 +08:00
김강현 b7c9f0e6ff chore(i18n): improve Korean locale translations for copy and delete actions (#5280) 2025-11-26 12:34:54 +08:00
Steven 424f11f227 fix(store): fix PostgreSQL tag filtering type inference error
Resolves issue where tag filtering in PostgreSQL databases failed with "operator does not exist: jsonb ~~ unknown" error. The hierarchical tag filtering feature introduced in commit 5e47f25b generated SQL with implicit type placeholders that PostgreSQL couldn't infer.

The fix explicitly casts the LIKE comparison placeholder to text (::text) in the PostgreSQL dialect, ensuring proper type resolution for the query parameter.

Fixes #5275

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 07:40:39 +08:00
Steven 68c17469a3 fix(markdown): fix UTF-8 truncation for CJK characters in snippet generation
The truncateAtWord function was slicing strings by byte position instead of
character position. When truncating text with multi-byte UTF-8 characters
(like CJK), this could cut in the middle of a character, creating invalid
UTF-8 and causing gRPC marshaling errors.

Fixed by converting to runes before truncation to ensure we always cut at
proper character boundaries. Added test cases for CJK characters.

Fixes #5276

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 07:34:28 +08:00
Steven e17cd163c6 chore: bump version 2025-11-25 22:17:45 +08:00
Steven eb541d04cc fix(web): resolve tag sidebar filtering and reactivity issues
This fixes multiple issues with the tag sidebar and activity calendar:

1. Tag disappearing bug: When filtering by a tag, the sidebar now shows all tags instead of only the selected tag
2. Activity calendar filtering: Calendar now shows full activity history instead of filtered results
3. Auto-update on memo changes: Sidebar tags and calendar now update automatically when creating/editing memos without requiring manual page refresh

Technical changes:
- Modified useFilteredMemoStats to fetch unfiltered UserStats from backend API for Home/Profile pages
- Fixed key mismatch bug in userStore where stats were stored with inconsistent keys
- Added statsStateId update in fetchUserStats to trigger reactivity
- Updated MainLayout to pass appropriate userName based on page context
- Archived/Explore pages continue to compute from cached memos (correct behavior)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 22:17:01 +08:00
Steven 8ec4c9ab63 fix(web): update time locale when language is changed
Pass i18n.language to time display components to ensure locale updates
when the user switches languages in UserMenu. Changes:

- MemoView: Pass i18n.language to toLocaleString() and <relative-time> lang attribute
- MonthNavigator: Wrap with observer to make component reactive to i18n.language changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:37:04 +08:00
Steven ef6456a4f5 refactor(web): restructure MemoEditor with custom hooks and improved error handling
Extract reusable logic into custom hooks (useLocalFileManager, useDragAndDrop, useDebounce, useAbortController), add ErrorBoundary for resilience, and centralize constants. Fix cursor positioning bugs, useEffect dependency issues, and add geocoding request cancellation. Improve performance with debounced localStorage writes and ref-based flags.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 21:29:54 +08:00
Johnny 1832b59190 fix(css): standardize color variable values in default-dark theme 2025-11-25 09:02:57 +08:00
Steven 5e95a77f50 chore: update color variables in default-dark theme for improved contrast 2025-11-24 21:59:24 +08:00
Steven b5de847107 chore(web): add external link icon for memo attachments 2025-11-24 21:56:14 +08:00
Steven 424e599980 refactor(web): optimize memo statistics fetching by using cached data from memo store 2025-11-24 21:37:12 +08:00
Steven 72f93c5379 feat(web): enhance file upload handling with local file support and preview 2025-11-24 21:31:18 +08:00
Steven 1d582e0f39 chore: upgrade dependencies 2025-11-24 20:18:52 +08:00
Richard Szegh 455eef9fa3 feat(web): add ability to delete unused attachments (#5272) 2025-11-24 11:55:53 +08:00
Johnny 60d977c0bf fix: add period to comment for golangci-lint compliance 2025-11-23 23:47:17 +08:00
Johnny b78d4c2568 refactor(markdown): use Unicode categories for tag validation
Replace custom character whitelist with Unicode standards-based validation:

- Use unicode.IsLetter/IsNumber/IsSymbol instead of hardcoded lists
- Remove manual UTF-8 byte checking for CJK punctuation
- Add proper rune-based length limiting (MAX_TAG_LENGTH = 100)
- Improve international character support (CJK, Arabic, Cyrillic, etc.)
- Add emoji support via unicode.IsSymbol

Benefits:
- Cleaner, more maintainable code (~50 lines removed)
- Standards-based approach following Unicode categories
- Better UTF-8 safety with utf8.DecodeRune
- Consistent validation between Go backend and TypeScript frontend

All existing tests pass with improved Unicode handling.
2025-11-23 23:45:10 +08:00
Steven d69435c97c chore(docs): update security policy to prevent public vulnerability disclosure
- Direct security reports to email only instead of public GitHub issues
- Set clear expectations: no CVEs during beta (v0.x) phase
- Add security best practices for self-hosted deployments
- Plan formal vulnerability disclosure program for v1.0+

Addresses #5255
2025-11-21 09:13:40 +08:00
gitkeniwo a533ba02dc fix: add load more button and pagination to attachments page (#5258) 2025-11-21 09:04:41 +08:00
Steven edfbd6b073 fix(web): refresh sidebar tags when creating/updating memos
The sidebar tag list wasn't updating when users created new memos with tags
or modified existing memo tags. This was because useFilteredMemoStats hook
only refetched when filter/state/orderBy changed.

Now the hook observes memoStore.state.stateId, which changes whenever memos
are created, updated, or deleted. This triggers automatic refetch and the
sidebar updates immediately with the latest tag counts.

Fixes tag refresh issue in sidebar
2025-11-19 22:30:00 +08:00
Steven cabd0d61c6 fix(web): resolve Leaflet DOM cleanup error causing app crashes
- Add MapCleanup component to properly remove Leaflet map instances on unmount
- Fix LocationMarker initialization with useRef to prevent re-initialization
- Remove problematic key prop in LocationDialog that caused unnecessary remounts
- Fix goimports formatting in tag parser

Fixes #5260
2025-11-19 22:21:01 +08:00
Steven 3989100a27 fix(parser): handle additional Unicode punctuation in tag parsing 2025-11-19 22:19:56 +08:00
Steven 64e9d82d67 fix(parser): support Unicode characters in tags
Fixes #5264

Chinese, Japanese, Korean, and other Unicode characters are now
properly recognized in hashtags, following the standard hashtag
parsing conventions used by Twitter, Instagram, and GitHub.

Changes:
- Updated tag parser to allow Unicode letters and digits
- Tags stop at whitespace and punctuation (both ASCII and CJK)
- Allow dash, underscore, forward slash in tags
- Added comprehensive tests for CJK characters and emoji

Examples:
- #测试 → recognized as tag '测试'
- #日本語 → recognized as tag '日本語'
- #한국어 → recognized as tag '한국어'
- #测试。→ recognized as tag '测试' (stops at punctuation)
- #work/测试/项目 → hierarchical tag with Unicode
2025-11-19 22:06:11 +08:00
Neo 4de8712cb0 fix: keyboard shortcuts (#5250) 2025-11-17 08:55:57 +08:00
Johnny 357118804e feat(web): add Focus Mode UI entry in Insert Menu
Add discoverable UI entry point for Focus Mode via Insert Menu submenu:

UI Changes:
- Add "View" submenu to Insert Menu (+ button dropdown)
- Nested menu with Focus Mode option (ChatGPT-style pattern)
- Display keyboard shortcut hint (⌘⇧F) next to menu item
- Uses DropdownMenuSub components from Radix UI

User Access Methods:
1. Keyboard: Cmd/Ctrl+Shift+F (primary, power users)
2. Mouse: + menu → View → Focus Mode (discoverable)
3. Mobile: Touch-friendly menu access

Benefits:
- Improves discoverability for new users
- Doesn't clutter main editor UI
- Educates users about keyboard shortcut
- Extensible for future view options (typewriter, reading mode, etc.)
- Follows familiar UI patterns (ChatGPT, Notion)

Files Modified:
- web/src/components/MemoEditor/ActionButton/InsertMenu.tsx
  * Add DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent
  * Add View submenu with Focus Mode entry
  * Add onToggleFocusMode prop
- web/src/components/MemoEditor/index.tsx
  * Pass toggleFocusMode to InsertMenu component
- web/src/locales/en.json
  * Add "editor.view" translation key
2025-11-17 08:55:10 +08:00
Johnny c8162ff3cc feat(web): add Focus Mode for distraction-free writing
Add keyboard-activated Focus Mode to provide an immersive writing experience:

Features:
- Toggle with Cmd/Ctrl+Shift+F (matches GitHub, Google Docs)
- Exit with Escape, toggle shortcut, button click, or backdrop click
- Expands editor to ~80-90% of viewport with centered layout
- Semi-transparent backdrop with blur effect
- Maintains all editor functionality (attachments, shortcuts, etc.)
- Smooth 300ms transitions

Responsive Design:
- Mobile (< 640px): 8px margins, 50vh min-height
- Tablet (640-768px): 16px margins
- Desktop (> 768px): 32px margins, 60vh min-height, 1024px max-width

Implementation:
- Centralized constants for easy maintenance (FOCUS_MODE_STYLES)
- Extracted keyboard shortcuts and heights to named constants
- JSDoc documentation for all new functions and interfaces
- TypeScript type safety with 'as const'
- Explicit positioning (top/left/right/bottom) to avoid width overflow

Files Modified:
- web/src/components/MemoEditor/index.tsx - Main Focus Mode logic
- web/src/components/MemoEditor/Editor/index.tsx - Height adjustments
- web/src/locales/en.json - Translation keys

Design follows industry standards (GitHub Focus Mode, Notion, Obsidian)
and maintains code quality with single source of truth pattern.
2025-11-16 23:15:36 +08:00
Steven 156908c77f chore(web): migrate from ESLint+Prettier to Biome
- Install @biomejs/biome@2.3.5 as unified linter and formatter
- Remove ESLint, Prettier and all related plugins (221 packages removed)
- Migrate linting rules from ESLint to Biome configuration
- Migrate formatting rules from Prettier to Biome configuration
- Exclude auto-generated proto files from linting (src/types/proto/**)
- Exclude CSS files from Biome (Tailwind syntax not yet supported)
- Update package.json scripts:
  - lint: tsc + biome check
  - lint:fix: biome check --write
  - format: biome format --write
- Auto-fix import organization across 60+ files
- Fix duplicate key in Russian locale (ru.json)
- Update CLAUDE.md documentation to reflect Biome usage

Benefits:
- 10-100x faster linting performance
- Simplified toolchain with single configuration file
- 221 fewer npm dependencies
- Unified linting, formatting, and import organization
2025-11-14 23:58:07 +08:00
Johnny 64111369d3 fix(web): refactor task list styles to follow GitHub standard (#5253)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-14 23:37:00 +08:00
Steven d1b2c0308b chore: add demo user access token for testing purposes 2025-11-11 08:31:05 +08:00
Steven dc398cf6a7 chore(web): unify metadata badge styling and fix event handling
- Remove MetadataBadge component and inline styles consistently
- Add pointer/mouse event handlers to prevent drag interference
- Fix LocationDisplay mode handling and popover interaction
- Clean up RelationList empty state logic
2025-11-10 21:53:56 +08:00
boojack 659c63165b chore: add Vercel OSS Program badge
Added Vercel OSS Program badge to README.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-11-10 20:18:41 +08:00
Johnny 9a100d55be chore(server): remove profiler code and endpoints (#5244)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-10 20:17:21 +08:00
Simon bb3d808e0e feat: allow closing image preview via backdrop click (#5243) 2025-11-10 19:12:45 +08:00
Johnny 6fc0ef7cc2 chore(web): remove redundant and minimal README files
Removed 3 markdown files that provided no useful documentation:
- web/README.md: Single line "The frontend of Memos" (redundant)
- web/src/components/kit/README.md: Single line "Base components" (minimal)
- web/MARKDOWN_STYLE_GUIDE.md: Outdated styling guide (no longer applicable)

Kept comprehensive documentation files:
- web/src/components/MasonryView/README.md (implementation details)
- web/src/themes/COLOR_GUIDE.md (design system guide)
- web/src/components/ConfirmDialog/README.md (component API docs)
- web/src/store/README.md (architecture patterns)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 14:21:10 +08:00
Johnny fa3e0fc7f9 fix(web): make MermaidBlock reactive to system theme changes and improve code quality
- Add system theme listener to detect OS theme changes in real-time
- Refactor to eliminate duplicate theme preference extraction
- Simplify getMermaidTheme function from switch statement to ternary
- Move render guard outside async function for better readability
- Update comments to be more concise and focused

The component now properly re-renders Mermaid diagrams when the OS theme changes while using "system" theme preference.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 14:19:11 +08:00
Johnny fb736c20d3 feat(web): add Mermaid diagram support in markdown (#5242)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 14:13:10 +08:00
Johnny 5925e3cfc1 chore(web): simplify command system and improve editor UX (#5242)
Streamlines the command suggestion interface and fixes list auto-completion behavior:

- Remove command descriptions for cleaner suggestion popup UI
- Replace PaperclipIcon with FileIcon for semantic accuracy
- Fix list auto-completion to avoid extra newline when exiting list mode
- Add explanatory comments for cursor offset positions
- Improve dependency array in useListAutoCompletion hook

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 13:09:50 +08:00
Johnny fc43f86571 chore(web): unify Location/Attachments/Relations components (#5241)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 07:23:31 +08:00
Johnny a2ccf6b201 feat(web): improve list auto-completion and tag insertion UX (#5240)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 01:26:29 +08:00
Johnny e8b0273473 chore(web): improve CommandSuggestions and TagSuggestions components (#5239)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-09 01:05:24 +08:00
Johnny bd21338fdb fix(web): markdown list auto-completion creates new line correctly (#5238)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 10:47:10 +08:00
Johnny c54fcf7aa7 refactor(web): redesign Settings components (#5237)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 10:32:55 +08:00
Steven 805bb4e741 chore(github): streamline issue templates with validation and better structure
Improve bug report and feature request templates to reduce duplicate submissions and gather better information:

Bug Report Template:
- Add pre-submission checklist requiring users to search existing issues and test on latest version/demo
- Add dropdown for issue location (stable, dev, demo site, older version)
- Restructure fields with clearer labels and better placeholders
- Add "Expected Behavior" section for clarity
- Combine screenshots and context with helpful prompts

Feature Request Template:
- Add pre-submission checklist to confirm issue search
- Expand feature type categories (API/Backend, Integrations/Plugins, Security/Privacy, Performance)
- Add "Problem or Use Case" field to understand the underlying need
- Add "Alternatives Considered" section
- Improve placeholders with specific examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 10:28:51 +08:00
boojack 906412013f refactor(api): remove test_auth.go and inline test helpers (#5235)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 09:53:29 +08:00
boojack 13fea64d15 fix(api): implement custom memo ID support in CreateMemo (#5234)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 09:43:10 +08:00
Steven ef9eee19d6 fix: implement tag suggestions functionality
Backend changes:
- Fix ListAllUserStats to calculate and return tag statistics
- Previously only returned name and timestamps, missing TagCount
- Now properly aggregates tags, pinned memos, and memo type stats

Frontend changes:
- Initialize user stats on app startup to populate tag data
- Show all tags when typing just '#' (fix empty Fuse.js search)
- Auto-refresh stats after creating/updating/deleting memos
- Fix Checkbox component ref warning with forwardRef

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 09:15:38 +08:00
boojack 7d4d1e8517 feat(web): standardize theme system with auto sync option (#5231)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 00:41:21 +08:00
Steven 8f29db2f49 fix(server): prevent memory exhaustion in thumbnail generation
Address high memory usage when opening resource tab (fixes #5183) by implementing:

1. Concurrency control: Limit thumbnail generation to 3 concurrent operations using semaphore to prevent memory exhaustion when many images are requested simultaneously

2. S3 optimization: Skip server-side thumbnail generation for S3-stored images by default. S3 images now use presigned URLs directly, avoiding:
   - Downloading large images from S3 into server memory
   - Decoding and resizing images on the server
   - High memory consumption during batch requests

3. Memory management improvements:
   - Explicitly clear blob and decoded image from memory after use
   - Restructure thumbnail cache check to avoid unnecessary semaphore acquisition
   - Double-check pattern to prevent duplicate generation while waiting

This restores the original S3 behavior before commit e4f6345 while maintaining thumbnail support for local/database storage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 09:04:21 +08:00
Steven b7215f46a6 refactor(web): use Radix Checkbox and remove memoTypeStats
- Replace native input with Radix UI Checkbox in TaskListItem for better accessibility and consistent styling
- Remove memoTypeStats tracking and display (link count, todo count, code count)
- Remove StatCard component and related type definitions
- Simplify statistics to only track activity calendar data and tags

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 08:36:15 +08:00
Steven 8f136ffa75 fix(api): correct user registration logic and first-user detection
- Changed first-user detection to check for any users instead of only HOST users
- Moved registration setting check before role assignment to properly block unauthorized registrations
- Fixed role assignment logic to ensure unauthenticated users always get USER role
- Updated test cases to create host user first when not testing first-user scenario

This ensures the first user is always created as HOST and registration settings are properly enforced for subsequent user creation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 23:41:47 +08:00
boojack 21d31e3609 fix(security): implement security review recommendations (#5228)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-06 23:32:27 +08:00
Elliott bb8fa90496 feat(i18n): add missing translations for zh-Hans (closes #5209) (#5229) 2025-11-06 22:32:03 +08:00
Steven 32d47abef2 fix(api): use correct instance setting method in user registration
Replace non-existent GetWorkspaceGeneralSetting with GetInstanceGeneralSetting
to properly check if user registration is allowed. This fixes a compilation
error that was preventing tests from running.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 20:00:35 +08:00
Florian Dewald 769dcd0cf9 fix(security): add missing authorization checks to various services (#5217) 2025-11-06 19:42:44 +08:00
boojack df93120f60 chore: add Claude Code GitHub workflow (#5227) 2025-11-06 19:40:01 +08:00
boojack 6cff7972d5 fix(web): fix tag syntax rendering on first line (#5226)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-06 19:29:16 +08:00
Steven 8f0658e90d feat(web): enhance inbox notifications and user profile layouts
- Polish inbox notification items with improved visual hierarchy
  - Add original memo snippet with left border indicator
  - Redesign comment preview with gradient background and primary accent
  - Increase spacing and improve typography with consistent sizing
  - Add ring borders to avatars and refined icon badges
  - Enhance loading and error states with better skeleton designs
  - Improve hover states and transitions throughout

- Redesign user profile header layout
  - Create full-width centered header with avatar and user info
  - Add horizontal layout for profile actions
  - Improve responsive design with proper flex wrapping
  - Allow memo list to use full width for masonry layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:41:30 +08:00
Steven 71d0dbaf41 chore: fix linter 2025-11-05 23:59:24 +08:00
Steven 89b0b81bdc fix(web): add required headers for Nominatim reverse geocoding API
Nominatim's usage policy requires a User-Agent header to identify the application. Added User-Agent and Accept headers to the reverse geocoding fetch request, and improved error handling to check HTTP response status.

Fixes #5222

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 23:47:44 +08:00
Steven 4c1d1c70d1 refactor: rename workspace to instance throughout codebase
Remove work-related terminology by renaming "workspace" to "instance"
across the entire application. This change better reflects that Memos
is a self-hosted tool suitable for personal and non-work use cases.

Breaking Changes:
- API endpoints: /api/v1/workspace/* → /api/v1/instance/*
- gRPC service: WorkspaceService → InstanceService
- Proto types: WorkspaceSetting → InstanceSetting
- Frontend translation keys: workspace-section → instance-section

Backend Changes:
- Renamed proto definitions and regenerated code
- Updated all store layer methods and database drivers
- Renamed service implementations and API handlers
- Updated cache from workspaceSettingCache to instanceSettingCache

Frontend Changes:
- Renamed service client: workspaceServiceClient → instanceServiceClient
- Updated all React components and state management
- Refactored stores: workspace.ts → instance.ts
- Updated all 32 locale translation files

All tests pass and both backend and frontend build successfully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 23:35:35 +08:00
boojack d98ee36178 chore: standardize and improve API structure (#5224)
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-05 22:36:51 +08:00
Florian Dewald 5f57f48673 fix(security): validate attachment filenames (#5218) 2025-11-05 08:48:55 +08:00
Steven 1d7efb1580 refactor(web): unify memo stats/filters with context-aware MainLayout
Create unified architecture for memo statistics, filters, and sorting
across all pages (Home, Explore, Archived, Profile) with proper
visibility filtering and consistent data flow.

Key changes:
- Rename HomeLayout → MainLayout to reflect broader usage
- Create useFilteredMemoStats hook for unified stats computation
- Create useMemoFilters/useMemoSorting hooks to eliminate duplication
- Refactor all pages to use unified hooks (~147 lines removed)
- Move Explore route under MainLayout (was sibling before)
- Fix masonry column calculation threshold (1024px → 688px+)

Architecture improvements:
- MainLayout computes filter/stats per route context
- Stats/tags based on same filter as memo list (consistency)
- Proper visibility filtering (PUBLIC/PROTECTED) on Explore
- MemoExplorer/StatisticsView accept stats as required props
- Eliminated optional fallbacks and redundant data fetching

Benefits:
- Single source of truth for stats computation
- Stats remain static (don't change with user filters)
- Reduced code duplication across 4 pages
- Better maintainability and type safety
- Proper security (no private memo leakage on Explore)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 08:46:52 +08:00
Steven d30ff2898f fix(web): correct task checkbox toggling in multi-section memos
Fixed a bug where clicking checkboxes in task lists would toggle the wrong
checkbox when a memo contained multiple sections with separate task lists.

The issue was that TaskListItem was counting tasks only within the immediate
parent list (ul/ol), but the toggleTaskAtIndex function counts all tasks
globally across the entire memo. This caused index misalignment.

Changes:
- Add containerRef to MemoContentContext for proper task scoping
- Pass memoContentContainerRef through context in MemoContent component
- Update TaskListItem to count all tasks within the container scope

This ensures task indices are calculated consistently with the markdown
manipulation logic, fixing checkbox toggling in complex multi-section memos.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 09:25:15 +08:00
Claude 9b72963e08 feat: replace HomeSidebar with MemoExplorer and MemoExplorerDrawer components 2025-11-02 23:31:29 +08:00
Claude dc9470f71c feat: implement OAuth state management with CSRF protection and cleanup functionality 2025-11-02 23:23:44 +08:00
Claude fb01b49ecf feat: add VisuallyHidden component and enhance LocationDialog accessibility 2025-11-02 23:02:08 +08:00
Claude 638b22a20d chore: implement InsertMenu with file upload and memo linking functionality 2025-11-02 22:53:07 +08:00
Steven 93964827ad refactor: redesign memo editor action bar UI
- Replace multiple action buttons with unified InsertMenu dropdown
- Consolidate upload, link memo, and location into single + button
- Redesign VisibilitySelector with text-based dropdown UI
- Unify badge styling for location, attachments, and links
  - Consistent height (h-7), padding, gaps, and border styles
  - Secondary foreground text color with hover states
  - Max width with truncation for long content
- Add image thumbnails in attachment badges
- Simplify button hierarchy with ghost variant for save/cancel
- Remove obsolete components (TagSelector, MarkdownMenu, etc.)
- Extract LocationView to separate component for better organization

Fixes #5196
2025-10-31 21:29:58 +08:00
Steven 1ced0bcdbd chore: fix linter 2025-10-31 08:36:12 +08:00
Steven bc1550e926 refactor(api): migrate inbox functionality to user notifications
- Remove standalone InboxService and move functionality to UserService
- Rename inbox to user notifications for better API consistency
- Add ListUserNotifications, UpdateUserNotification, DeleteUserNotification methods
- Update frontend components to use new notification endpoints
- Update store layer to support new notification model

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 08:33:09 +08:00
Steven e915e3a46b refactor(web): refactor MemoFilters component and add comprehensive filter support
- Refactored MemoFilters.tsx for better maintainability:
  * Centralized filter configuration with FILTER_CONFIGS object
  * Added TypeScript interfaces for type safety
  * Removed separate FactorIcon component
  * Extracted handleRemoveFilter function
  * Improved imports organization

- Polished MemoFilters UI styles:
  * Changed to modern pill/badge design with rounded-full
  * Enhanced spacing and color schemes
  * Added smooth transitions and hover effects
  * Improved interactive remove button with destructive color hints
  * Better text readability with font-medium

- Added comprehensive filter support to all pages:
  * Explore page: Added full filter support (was missing)
  * Archived page: Enhanced from basic to full filter support
  * UserProfile page: Enhanced from basic to full filter support
  * All pages now support: content search, tag search, pinned, hasLink, hasTaskList, hasCode, and displayTime filters

- Consistency improvements:
  * All pages using PagedMemoList now have identical filter logic
  * Respects workspace settings for display time (created/updated)
  * Unified filter behavior across Home, Explore, Archived, and UserProfile pages
2025-10-30 22:52:58 +08:00
Steven 1e954070b9 refactor(web): improve memo component skeleton and loading states 2025-10-30 22:25:19 +08:00
Steven 5e47f25bf5 feat(store): add hierarchical tag filtering support
Tag filters now support hierarchical matching where searching for a tag (e.g., "book") will match both the exact tag and any tags with that prefix (e.g., "book/fiction", "book/non-fiction"). This applies across all database backends (SQLite, MySQL, PostgreSQL) with corresponding test updates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 00:21:53 +08:00
boojack a2bfba6928 chore: update readme
Added LambdaTest to sponsorship section

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-30 00:16:40 +08:00
Steven f65633e8a9 chore: fix linter issues in backend and frontend
- Remove extra blank line in memo_service.go (goimports)
- Remove invalid fields from CreateMemoRequest call (validateOnly, requestId)
- Clean up unnecessary comments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:41:20 +08:00
Steven 243ecf14b0 refactor(api): remove DeleteMemoTag and RenameMemoTag endpoints
BREAKING CHANGE: Removed DeleteMemoTag and RenameMemoTag API endpoints
for better API consistency. Tags should now be managed by updating memo
content directly via UpdateMemo endpoint.

Backend changes:
- Remove RenameMemoTag and DeleteMemoTag RPC methods from proto
- Remove backend implementations in memo_service.go
- Regenerate protocol buffers (Go, TypeScript, OpenAPI)

Frontend changes:
- Remove RenameTagDialog component
- Simplify TagsSection to remove rename/delete functionality
- Improve tag styling with active state highlighting
- Add smooth transitions and better hover interactions
- Polish TagTree component for consistency
- Tags now only support click-to-filter (no inline editing)

Style improvements:
- Active tags highlighted with primary color and font-medium
- Consistent hover states across flat and tree views
- Better spacing and visual hierarchy
- Improved empty state styling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:32:47 +08:00
Steven d794c0bf8b feat(web): improve loading performance with skeleton screens and parallel fetches
- Add MemoSkeleton component for smooth initial page load experience
- Integrate skeleton loader into PagedMemoList during initial fetch
- Parallelize user settings and shortcuts API calls (~50% faster session init)
- Batch-fetch memo creators in parallel to eliminate individual loading spinners
- Pass showCreator prop to Explore page for proper skeleton rendering

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 23:53:35 +08:00
Steven 2371bbb1b7 feat(web): add quick language and theme switchers to user menu
- Add language and theme selector submenus to UserMenu component for quick access
- Refactor shared utilities: extract THEME_OPTIONS constant and getLocaleDisplayName() function
- Update LocaleSelect and ThemeSelect to use shared utilities, eliminating code duplication
- Make UserMenu reactive with MobX observer for real-time setting updates
- Fix language switching reactivity by immediately updating workspaceStore.state.locale
- Add scrollable menu support for language selector (max-h-[90vh])
- Apply same instant locale update to PreferencesSection for consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 22:32:25 +08:00
Steven d693142dd4 feat(web): enhance code blocks with copy button and fix link navigation
Add custom code block renderer with language display and copy functionality. Links now open in new windows, and clicking image links no longer triggers both link navigation and image preview.

- Add CodeBlock component with copy-to-clipboard button and language label
- Configure all markdown links to open in new windows with target="_blank"
- Fix image link behavior to prevent duplicate actions when clicked

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 22:06:07 +08:00
Steven b00df8a9d1 fix(web): remove error notifications for location geocoding failures
Remove disruptive error toasts when reverse geocoding or geolocation fails.
Instead, silently fall back to using coordinates as the location placeholder.
This improves UX for users in regions where OpenStreetMap is restricted
(e.g., China) or when CSP blocks external API calls.

Fixes #5198, #5197

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 21:28:29 +08:00
Steven 5f7c758f38 fix(web): make layout and direction settings reactive in UI
Fixed issue #5194 where changing the layout (List/Masonry) or sort direction
didn't update the UI until page refresh. The root cause was that ViewState
fields weren't marked as MobX observables, so the UI didn't react to changes
even though values were being persisted to localStorage.

Solution: Added constructor to ViewState that marks orderByTimeAsc and layout
fields as observable, following the same pattern used in other stores like
MemoFilterState.

Fixes #5194

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 07:58:15 +08:00
Steven 91a7e927a5 fix(server): reduce static asset cache to prevent stale files after redeploy
Changed Cache-Control max-age from 7 days to 1 hour with immutable directive.
This prevents users from experiencing blank pages or JS errors when accessing
frequently redeployed instances (e.g., demo environments) where old cached
assets may reference files that no longer exist after redeployment.

Since Vite generates content-hashed filenames, the immutable directive prevents
unnecessary revalidation while the shorter cache duration ensures fresh assets
are served within an hour of redeployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 07:55:02 +08:00
Steven 2197178dd7 chore: update README for clarity and consistency 2025-10-28 07:46:45 +08:00
boojack d516f9aab2 chore: tweak readme
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-27 23:41:24 +08:00
Steven f635d85bcf chore: fix reactions seed data
- Add comprehensive inline documentation for auth services
- Document session-based and token-based authentication flows
- Clarify authentication priority and validation logic
- Add detailed comments for JWT token structure and claims
- Fix reactions seed data to use memo UIDs instead of numeric IDs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 20:27:27 +08:00
Claude f241b590a2 chore: update demo data 2025-10-27 09:20:26 +08:00
Claude 596b894ca0 chore: remove unused syntax
- Removed the wikilink extension from markdown services in test and API service.
- Deleted the DefaultLink and WikiLink components, simplifying link handling.
- Updated ConditionalComponent to remove wikilink checks.
- Adjusted MemoContent to exclude wikilink handling in markdown rendering.
- Refined markdown styles for compact rendering, enhancing readability.
- Added a Markdown Styling Guide to document the new compact styling approach.
2025-10-27 08:31:57 +08:00
Claude 7eec424274 chore: remove references handling from markdown extraction 2025-10-27 00:12:24 +08:00
Claude 6cb96ef65e chore: add missing punctuation in comments 2025-10-26 11:58:34 +08:00
Claude 739fd2cde6 refactor: update markdown parser
- Removed the `nodes` field from the `Memo` interface in `memo_service.ts`.
- Updated the `createBaseMemo` function and the `Memo` message functions to reflect the removal of `nodes`.
- Cleaned up the serialization and deserialization logic accordingly.

chore: remove code-inspector-plugin from Vite configuration

- Deleted the `codeInspectorPlugin` from the Vite configuration in `vite.config.mts`.
- Simplified the plugins array to include only `react` and `tailwindcss`.
2025-10-26 11:28:40 +08:00
Steven bfad0708e2 fix(web): make memoFilterStore reactive by marking fields as observable
Fixes the root cause of non-reactive filtering. The MemoFilterState class
was not marking its fields as observable in MobX, so changes to the filters
array were not being tracked.

Added makeObservable configuration to mark:
- filters and shortcut as observable
- addFilter, removeFilter, removeFiltersByFactor, clearAllFilters, setShortcut as actions

This ensures that when tags are clicked and filters are added/removed,
MobX observer components will re-render and fetch new data.

Related to #5189

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 07:01:27 +08:00
Steven e0b1153269 fix(web): resolve MobX observable reactivity issue in filter computation
Fixes filtering functionality that was broken due to improper use of
useMemo with MobX observables. The issue occurred because useMemo's
dependency array uses reference equality, but MobX observable arrays
are mutated in place (reference doesn't change when items are added/removed).

Changes:
- Remove useMemo from filter computation in Home, UserProfile, and Archived pages
- Calculate filters directly in render since components are already MobX observers
- Fix typo: memoFitler -> memoFilter in Archived.tsx

This ensures filters are recalculated whenever memoFilterStore.filters changes,
making tag clicks and other filter interactions work correctly.

Fixes #5189

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 06:59:13 +08:00
Steven 46ce0bc62e fix(store): correct PostgreSQL placeholder generation in IN clauses
Fixes a regression introduced in v0.25.2 where PostgreSQL IN clause
placeholders were not properly incremented, causing all parameters to
use the same placeholder index (e.g., $1, $1, $1 instead of $1, $2, $3).

This bug affected:
- ListReactions (ContentIDList) - caused "failed to list reactions" errors
- ListAttachments (MemoIDList)
- ListMemos (IDList and UIDList)

The fix combines placeholder generation and argument appending into a
single loop to ensure proper incrementing.

Fixes #5188

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 06:47:06 +08:00
Steven 0c0d2a6294 chore: bump version 2025-10-24 08:15:32 +08:00
Claude 455665a16b docs: enhance README with improved feature descriptions and formatting 2025-10-23 22:25:54 +08:00
boojack f2f2a5159c chore: tweak README to enhance sponsorship and clarity
Updated README to include sponsorship details and enhance clarity on features and benefits.

Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-10-23 21:49:15 +08:00
Florian Dewald e4f6345342 feat: generate thumbnails for images stored in S3 and generate thumbnails with a maximum size (#5179) 2025-10-23 21:29:22 +08:00
Claude 16425ed650 feat(web): improve ReactionSelector UX with hover visibility
- Add hover-based visibility for reaction selector in memo cards
- Show reaction selector only on card hover or when popover is open
- Add onOpenChange callback to ReactionSelector for state management
- Reorder action buttons for better visual hierarchy
- Simplify conditional rendering of comment link
2025-10-23 21:20:15 +08:00
Claude 16e0049490 chore: improve layout and spacing in LocationSelector 2025-10-23 20:21:00 +08:00
Claude 7079790d4f feat: add copy content functionality to MemoActionMenu 2025-10-23 20:05:31 +08:00
Claude 686d31b357 feat: enhance attachment store with MobX observables and actions 2025-10-23 19:55:44 +08:00
Claude e35f16306e feat: add id as final tie-breaker in ListMemos 2025-10-23 19:44:41 +08:00
Steven c177871ab4 chore: remove outdated dependabot configuration and agents documentation 2025-10-23 19:16:21 +08:00
Steven f5624fa682 refactor: standardize MobX store architecture with base classes and utilities
Refactored all stores to follow consistent patterns and best practices while keeping MobX:

New Infrastructure:
- Created base-store.ts with StandardState base class and factory functions
- Added store-utils.ts with RequestDeduplicator, StoreError, and OptimisticUpdate helpers
- Added config.ts for MobX configuration and strict mode
- Created comprehensive README.md with architecture guide and examples

Server State Stores (API data):
- attachment.ts: Added request deduplication, error handling, computed properties, delete/clear methods
- workspace.ts: Added Theme type validation, computed memoization, improved initialization
- memo.ts: Enhanced with optimistic updates, request deduplication, structured errors
- user.ts: Fixed temporal coupling, added computed memoization, request deduplication

Client State Stores (UI state):
- view.ts: Added helper methods (toggleSortOrder, setLayout, resetToDefaults), input validation
- memoFilter.ts: Added utility methods (hasFilter, clearAllFilters, removeFiltersByFactor)

Improvements:
- Request deduplication prevents duplicate API calls (all server stores)
- Computed property memoization improves performance
- Structured error handling with error codes
- Optimistic updates for better UX (memo updates)
- Comprehensive JSDoc documentation
- Type-safe APIs with proper exports
- Clear separation between server and client state

All stores now follow consistent patterns for better maintainability and easier onboarding.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 19:13:42 +08:00
dependabot[bot] cce52585c4 chore: bump actions/setup-node from 4 to 5 (#5134)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 22:41:45 +08:00
Steven c09ea5a8ab chore: remove basic filter support from ListAttachments method 2025-10-22 22:41:24 +08:00
Steven 2e31bee1de fix: add missing period to comment per golangci-lint 2025-10-22 22:32:24 +08:00
Steven 9121ddbad9 feat(api): support username lookup in GetUser endpoint
- Update GetUser to accept both numeric IDs and username strings (users/{id} or users/{username})
- Implement CEL filter parsing for username-based lookups
- Update proto documentation to reflect dual lookup capability
- Simplify frontend user store to use GetUser instead of ListUsers filter
- Update ListUsers filter documentation to show current capabilities
2025-10-22 21:48:34 +08:00
Steven 4d4325eba5 chore: update component styles for consistency 2025-10-22 20:21:58 +08:00
Steven b4341dd123 fix(web): make reaction selector responsive with scrolling
- Replace fixed width (max-w-56) with responsive viewport-based width
- Use 90vw on mobile and max-w-md on desktop for better adaptability
- Add vertical scrolling with max-h-64 overflow-y-auto
- Increase grid columns to 8 on medium+ screens for better space utilization
- Ensures all reactions are accessible regardless of quantity

Fixes #5117

Co-authored-by: GitHub Copilot <noreply@github.com>
2025-10-22 19:31:58 +08:00
dependabot[bot] 07b523e4b2 chore: bump actions/setup-go from 5 to 6 (#5135)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 19:23:39 +08:00
dependabot[bot] 7a58250195 chore: bump actions/stale from 9.1.0 to 10.0.0 (#5136)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 19:23:25 +08:00
Simon 290cdf5d4f chore: use input type datetime-local instead of text (#5174) 2025-10-22 09:04:37 +08:00
Steven 2d4361d5fe chore: update memo content formatting and enhance link styling 2025-10-22 08:50:09 +08:00
Steven d8f7a4e739 chore: tweak demo data 2025-10-21 23:41:46 +08:00
Steven 81e852e3b5 chore: update gomark dependency 2025-10-21 23:09:27 +08:00
Steven b19e736f10 chore: tweak demo data 2025-10-20 23:58:49 +08:00
Steven b4ea7d843f feat: enhance memo sorting functionality to support multiple fields 2025-10-20 23:41:58 +08:00
Steven 95de5cc700 refactor: update migration history methods 2025-10-20 23:05:50 +08:00
Johnny bc7decf642 refactor: remove unused constants 2025-10-16 20:40:46 +08:00
Copilot b685ffacdf refactor: memo filter
- Updated memo and reaction filtering logic to use a unified engine for compiling filter expressions into SQL statements.
- Removed redundant filter parsing and conversion code from ListMemoRelations, ListReactions, and ListAttachments methods.
- Introduced IDList and UIDList fields in FindMemo and FindReaction structs to support filtering by multiple IDs.
- Removed old filter test files for reactions and attachments, as the filtering logic has been centralized.
- Updated tests for memo filtering to reflect the new SQL statement compilation approach.
- Ensured that unsupported user filters return an error in ListUsers method.
2025-10-16 09:22:52 +08:00
Steven 228cc6105d chore: update StatCard component for improved icon and count rendering in StatisticsView 2025-10-14 23:15:16 +08:00
Steven 56758f107c chore: refactor ActivityCalendar to use a calendar matrix and improve cell rendering 2025-10-14 21:12:43 +08:00
Steven 5011eb5d70 feat: enhance LocationSelector with improved geolocation handling 2025-10-14 20:23:14 +08:00
Ben Mitchinson 12c4aeeccc feat: lat/long input fields (#5152)
Signed-off-by: Ben Mitchinson <mitchinson.dev@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-14 20:07:01 +08:00
Steven 435cc7b177 feat: implement masonry layout with responsive columns and memo height tracking 2025-10-14 19:46:09 +08:00
Copilot 3245613a88 chore: cleanup components naming 2025-10-12 18:58:37 +08:00
asttool 54e3c13435 refactor: use WaitGroup.Go to simplify code (#5162)
Signed-off-by: asttool <asttool@outlook.com>
2025-10-10 22:28:35 +08:00
Huang Cheng Ting d7e751997d chore: update zh-Hant translation (#5159) 2025-10-09 21:30:55 +08:00
Nic Luckie 20233c7051 feat(web): add accessible ConfirmDialog and migrate confirmations; and Markdown-safe descriptions (#5111)
Signed-off-by: Nic Luckie <nicolasluckie@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-09 00:40:08 +08:00
Johnny 4056a1bada chore: update sponsors 2025-10-08 20:42:15 +08:00
Johnny efe6013c36 fix: add user authentication checks 2025-10-08 20:30:05 +08:00
Claude f6e025d583 feat: implement theme management with system preference detection and early application 2025-10-08 09:51:49 +08:00
dependabot[bot] 3514180721 chore: bump golang.org/x/crypto from 0.41.0 to 0.42.0 (#5141)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:30:37 +08:00
dependabot[bot] 184e975664 chore: bump mobx-react-lite from 4.1.0 to 4.1.1 in /web (#5137)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:40 +08:00
dependabot[bot] 1db86bcd30 chore: bump typescript-eslint from 8.44.0 to 8.45.0 in /web (#5138)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:31 +08:00
dependabot[bot] 0f19713fce chore: bump github.com/aws/aws-sdk-go-v2/config from 1.31.6 to 1.31.12 (#5139)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:25 +08:00
dependabot[bot] ca62b8cd0c chore: bump google.golang.org/protobuf from 1.36.8 to 1.36.9 (#5140)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:17 +08:00
dependabot[bot] cca33af8fd chore: bump google.golang.org/grpc from 1.75.0 to 1.75.1 (#5142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:28:06 +08:00
dependabot[bot] 763a0d0dea chore: bump golang.org/x/mod from 0.27.0 to 0.28.0 (#5143)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:58 +08:00
dependabot[bot] 498facdfbe chore: bump lucide-react from 0.486.0 to 0.544.0 in /web (#5144)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:48 +08:00
dependabot[bot] 698b08ae8d chore: bump tw-animate-css from 1.3.8 to 1.4.0 in /web (#5145)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 09:27:39 +08:00
dependabot[bot] e3890ca9be chore: bump typescript from 5.9.2 to 5.9.3 in /web (#5146)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-07 00:14:11 +08:00
boojack bcfcb1b554 docs: add sponsor section for Warp in README (#5127) 2025-10-01 05:25:42 +08:00
Claude c3a961229e fix: update cell opacity colors to use primary theme instead of destructive 2025-09-29 15:01:46 +08:00
github-actions[bot] 074c580214 chore: bump gomark
- Bump protoc-gen-go version from v1.36.8 to v1.36.9 in multiple generated files.
- Enhance OpenAPI descriptions for various endpoints to improve clarity and readability.
- Fix typo in the description list handling in the markdown service.
- Update HTMLElement component to handle children and self-closing tags correctly.
- Modify types in the markdown service to include children and self-closing properties for HTML elements.
2025-09-28 16:15:55 +08:00
Steven 8d8cc83fd8 chore: tweak assets link 2025-09-26 20:47:54 +08:00
Steven 7ab57f8ed2 chore: upgrade frontend dependencies 2025-09-17 21:51:58 +08:00
Steven 6d1485d168 fix: reset state on dialog close and improve dialog open handling 2025-09-17 21:51:46 +08:00
Steven 5ad2038b1a feat: update gomark dependency and refactor markdown parsing logic 2025-09-17 21:09:30 +08:00
Steven b7f792cbf7 chore: tweak development instructions 2025-09-17 08:48:27 +08:00
Steven f44b0850f4 feat: enhance CodeBlock component with theme-aware syntax highlighting 2025-09-16 19:08:28 +08:00
Steven c3d4f8e9d1 feat: implement user-specific SQL converter for filtering in user service 2025-09-10 21:05:26 +08:00
Steven 383553d3c8 feat: add DOMPurify for sanitizing HTML content in CodeBlock component 2025-09-10 20:52:51 +08:00
Giacomo Cerquone f4e23727bb fix: avoid hiding reaction selector and keep it always shown for mobile (#5079) 2025-09-09 11:35:21 +08:00
Giacomo Cerquone 60123de318 fix: update useEffect dependency to location.key so drawer is closed also when re-navigating to current route (#5077) 2025-09-08 16:26:18 +08:00
dependabot[bot] 3be1b3a1e3 chore: bump @radix-ui/react-checkbox from 1.3.2 to 1.3.3 in /web (#5062)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 22:57:34 +08:00
dependabot[bot] fb8a997248 chore: bump @radix-ui/react-dropdown-menu from 2.1.15 to 2.1.16 in /web (#5063)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 22:57:11 +08:00
dependabot[bot] b2a259d0ff chore: bump react-router-dom from 7.7.1 to 7.8.2 in /web (#5061)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 21:01:44 +08:00
dependabot[bot] b8fe953833 chore: bump @radix-ui/react-select from 2.2.5 to 2.2.6 in /web (#5065)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 21:01:34 +08:00
Steven 5a1af7b240 fix: adjust badge height 2025-09-02 23:18:11 +08:00
dependabot[bot] 0c516c83bd chore: bump nice-grpc-web from 3.3.7 to 3.3.8 in /web (#5056)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:34 +08:00
dependabot[bot] 9c67bbbbba chore: bump tw-animate-css from 1.3.6 to 1.3.7 in /web (#5053)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:23 +08:00
dependabot[bot] 74a44ac3e2 chore: bump actions/checkout from 4 to 5 (#5052)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:56:08 +08:00
dependabot[bot] fdbcd20ad1 chore: bump react-hot-toast from 2.5.2 to 2.6.0 in /web (#5051)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:55:57 +08:00
dependabot[bot] 56fd9fd7d5 chore: bump @bufbuild/protobuf from 2.6.2 to 2.7.0 in /web (#5057)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:47 +08:00
dependabot[bot] 9c456c3b72 chore: bump i18next from 25.3.2 to 25.4.2 in /web (#5058)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:34 +08:00
dependabot[bot] 1954eeb37b chore: bump github.com/spf13/cobra from 0.0.3 to 1.10.1 (#5059)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-02 22:21:21 +08:00
Johnny ebff15149b fix: use Fprint instead of Fprintf for development mode message 2025-08-31 20:38:07 +08:00
Johnny 3a7538f787 chore: fix linter 2025-08-31 20:29:40 +08:00
Johnny a373673087 chore: go mod tidy 2025-08-31 20:24:18 +08:00
Johnny 7cc2df9254 chore: fix linter 2025-08-31 20:22:32 +08:00
Johnny 3d1c197764 chore: upgrade golangci-lint version to v2.4.0 2025-08-31 19:50:55 +08:00
Johnny 9557150a87 chore: upgrade go version to 1.25 2025-08-31 19:45:41 +08:00
Johnny e427344e82 chore: upgrade dependencies 2025-08-31 13:14:10 +08:00
Johnny 12ab7e9dde chore: tweak docs 2025-08-27 21:35:04 +08:00
Johnny 3ba3f610c9 chore: upgrade typescript-eslint 2025-08-27 19:54:17 +08:00
Johnny 0b4252d1a3 chore: fix linter 2025-08-25 19:52:53 +08:00
Johnny cf29684882 chore: tweak links 2025-08-25 19:51:01 +08:00
Johnny 01c6aca788 chore: update readme with star history section 2025-08-24 22:43:49 +08:00
Xiang Jaywhen 016efe50a2 fix: update the link of Installation Guide (#5024)
Signed-off-by: Xiang Jaywhen <jaywhenx@gmail.com>
2025-08-24 20:24:46 +08:00
varsnotwars e2454a8ae4 chore: add test for ListMemos (#5015) 2025-08-19 21:57:38 +08:00
boojack c5a61ba89e chore: tweak README.md
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-08-18 22:13:58 +08:00
Steven 0d658088dc chore: bump version to 0.25.1 2025-08-18 20:21:30 +08:00
Steven e07e9f2e9f fix: theme selector 2025-08-18 20:08:53 +08:00
varsnotwars fbcdf0fba7 fix update theme not saving (#5012) 2025-08-18 01:39:48 +00:00
Johnny 01d3f2f86c chore: tweak dark theme 2025-08-17 21:11:54 +08:00
Johnny e93f3cbb8b refactor: unify theme and apperance 2025-08-17 11:27:59 +08:00
varsnotwars 4eb5b67baf feat: attachments by id (#5008) 2025-08-15 22:02:29 +08:00
Amazingca a3add85c95 fix: Update SSO login flow to encode redirect_uri (#5006)
Signed-off-by: Amazingca <autumn@amazingca.dev>
2025-08-15 08:45:19 +08:00
varsnotwars a9508b2546 chore: simplify convert reaction (#5001) 2025-08-14 00:06:23 +08:00
Sara Vieira 51d643c780 chore: default type to text/plain (#4993)
Signed-off-by: Sara Vieira <hey@iamsaravieira.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2025-08-13 20:09:02 +08:00
Liu Chao ba7dfb7d98 fix: OpenAPI Parameter Conflict in DeleteMemoTag Endpoint (#4985)
Signed-off-by: ChaoLiu <chaoliu719@gmail.com>
2025-08-13 07:14:18 +08:00
Huang Cheng Ting 5ba81d629c fix: prevent default focus behavior on open and close events in sheet (#4998) 2025-08-13 07:13:45 +08:00
Johnny 76ca258f23 chore: simplify update user settings 2025-08-11 23:19:56 +08:00
Huang Cheng Ting d86756f104 feat: add an option to auto expand subtags in tree mode (#4994) 2025-08-11 23:05:36 +08:00
varsnotwars 3fd305dce7 fix: preferences being overwritten (#4990) 2025-08-11 22:57:52 +08:00
Neo c76ffb0fe4 chore: adds a check to only query reactions when there are actual memos (#4984) 2025-08-10 14:25:35 +08:00
Jason Shawn D' Souza 1dd25634fd fix: Midi files show up as playable (#4991) 2025-08-10 14:23:41 +08:00
Neo 6b507ff600 fix: pinned shortcut comparison operators (#4987) 2025-08-10 14:22:54 +08:00
varsnotwars 9f8921d3b9 fix: preference not being saved (#4980)
Signed-off-by: varsnotwars <varsnotwars@protonmail.com>
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-08-08 22:50:46 +08:00
Sara Vieira 1f1add1a48 fix: add mime type check for file types (#4981) 2025-08-08 20:39:16 +08:00
Tobias Waslowski 15c146cfc5 feat(editor): create text-based autocompleting commands (#4971) 2025-08-08 18:55:59 +08:00
varsnotwars f4bdfa28a0 feat: filter/method for reactions by content_id (#4969) 2025-08-08 00:00:51 +08:00
Brandon Sprague 931ddb7c1c chore: add a new LOG_STACKTRACES option (#4973) 2025-08-07 23:56:21 +08:00
Johnny 8576001c83 fix: nl.json
Signed-off-by: Johnny <yourselfhosted@gmail.com>
2025-08-07 14:43:35 +08:00
Stephan Paternotte 1043fc8fba chore: update nl.json (#4974)
Signed-off-by: Stephan Paternotte <Stephan-P@users.noreply.github.com>
2025-08-07 14:40:53 +08:00
Colin Holzman 8319516d1a fix: boolean filters (#4966) 2025-08-06 21:06:15 +08:00
johnnyjoy 66b4f583a5 fix: linter 2025-08-06 20:22:20 +08:00
aarohee-he 0f2390a0b7 feat: add tooltips to editor buttons (#4934)
Co-authored-by: Anthony Cooper <antcoop096@gmail.com>
Co-authored-by: aarohee-he <aarohee-he@users.noreply.github.com>
Co-authored-by: Mishti Gala <mishtigala19@gmail.com>
2025-08-06 10:15:06 +08:00
boojack 13957472eb chore: merge visibility selector into save button
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-08-06 00:03:59 +08:00
johnnyjoy a5e441b622 chore: tweak dark mdoe styles 2025-08-05 21:07:59 +08:00
Liu Chao 3427ae75ba fix: resolve gRPC Gateway connection issue when server address is empty (#4968)
Signed-off-by: ChaoLiu <chaoliu719@gmail.com>
2025-08-05 19:42:20 +08:00
johnnyjoy 506b477d50 fix: get user by username 2025-08-04 19:56:12 +08:00
varsnotwars fa2fa8a5d7 refactor: remove call to db for parent memo name (#4947) 2025-08-04 19:39:52 +08:00
Huang Cheng Ting 896a3dccf2 chore: update zh-Hant translation (#4962) 2025-08-04 19:38:58 +08:00
johnnyjoy 34fb3f1514 chore: fix linter 2025-08-03 19:55:04 +08:00
Colin Holzman aae7ec8d1f fix: calendar filter (#4942) 2025-08-03 19:11:09 +08:00
Maximilian Krauß 4d6042e35f fix(tags): ensure JSON array elements are properly formatted in SQL queries (#4944) 2025-08-03 19:10:59 +08:00
XIN_____ 9c60165ba1 chore: update zh-Hans.json (#4940) 2025-08-03 19:10:49 +08:00
Andrea Marchetta 71464779dd fix: change itemCount into an Int64 (#4945) 2025-08-03 19:07:17 +08:00
dependabot[bot] 07e270564a chore: bump golang.org/x/net from 0.40.0 to 0.42.0 (#4948)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:49 +08:00
dependabot[bot] 94b58f0691 chore: bump google.golang.org/grpc from 1.72.2 to 1.74.2 (#4949)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:40 +08:00
dependabot[bot] 5a7693c90a chore: bump github.com/google/cel-go from 0.25.0 to 0.26.0 (#4951)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:30 +08:00
dependabot[bot] 11685c1f4d chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.82 to 1.18.2 (#4952)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:22 +08:00
dependabot[bot] a5711e893a chore: bump code-inspector-plugin from 0.18.3 to 1.0.4 in /web (#4954)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 19:05:17 +08:00
johnnyjoy b2a2151eaf chore: bump frontend dependencies 2025-08-03 18:17:21 +08:00
dependabot[bot] 9b06275f4c chore: bump vite from 7.0.1 to 7.0.6 in /web (#4957)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-03 12:46:05 +08:00
Colin Holzman 671f4bf88b fix: shortcuts list (#4936) 2025-07-31 19:52:13 +08:00
XIN_____ 79c7fcc8b6 chore: update zh-Hans.json (#4933) 2025-07-31 19:50:29 +08:00
Colin Holzman 6005d0f3f7 chore: use MEMOS_INSTANCE_URL for "Copy Link" (#4930) 2025-07-30 18:57:39 +08:00
Steven 1fcafd807e chore: enable memo comments by default 2025-07-29 22:31:18 +08:00
Johnny 5074268f4f fix: action styles in memo editor 2025-07-29 22:10:31 +08:00
Maximilian Krauß e724a7ef72 fix: disable profiler in production mode (#4925) 2025-07-29 19:22:41 +08:00
johnnyjoy 9971cbeed4 chore: fix linter 2025-07-29 19:20:59 +08:00
Johnny 8f51791da8 chore: update user setting definition 2025-07-29 09:21:51 +08:00
Johnny 3b8bfe72ea fix: linter 2025-07-27 23:35:01 +08:00
johnnyjoy c5d497a1f0 chore: update user settings 2025-07-27 23:12:42 +08:00
johnnyjoy 3f56ce47d2 chore: update definition of workspace setting 2025-07-27 15:50:09 +08:00
Anthony Cooper 53d3978507 chore: add hyperlink for 'releases page' (#4914) 2025-07-24 12:51:02 +08:00
Steven c5d2d15278 chore: fix eslint 2025-07-23 23:41:59 +08:00
Steven f78b277462 chore: simplify add memo relation 2025-07-23 23:34:30 +08:00
johnnyjoy 9b5b7b1ea2 Merge branch 'main' of https://github.com/usememos/memos 2025-07-23 22:22:15 +08:00
johnnyjoy c5767bf9d6 fix: eslint 2025-07-23 22:22:12 +08:00
Maximilian Krauß 2c7eb23343 feat(inbox): handles errors while fetching and adds possibility to delete items (#4908) 2025-07-23 14:21:26 +00:00
johnnyjoy db63b1949a chore: fix creator id format 2025-07-23 22:18:47 +08:00
johnnyjoy 9ea2f9f686 fix: linter 2025-07-23 22:13:48 +08:00
johnnyjoy ed23cbc011 refactor: memo filter 2025-07-23 22:10:16 +08:00
Steven 1a75d19a89 fix: memo filter for sqlite 2025-07-22 23:39:52 +08:00
Steven ac386c218d fix: workspace setting keys 2025-07-22 22:59:54 +08:00
Steven c133f5528a fix: workspace setting keys in frontend 2025-07-22 22:45:47 +08:00
johnnyjoy 6e45e9f8b6 refactor: deprecate old filter 2025-07-22 21:25:57 +08:00
johnnyjoy 7098721617 chore: fix linter 2025-07-22 21:15:23 +08:00
johnnyjoy e24f92b719 fix: tests 2025-07-22 21:13:24 +08:00
johnnyjoy b55904a428 feat: support more filter factors 2025-07-22 19:18:08 +08:00
Johnny 1a3fc4d874 fix: media width 2025-07-21 23:55:28 +08:00
johnnyjoy 6d9770b9c8 chore: move filter to filters 2025-07-21 21:52:00 +08:00
johnnyjoy 7481fe10bf chore: remove order by pinned 2025-07-21 21:45:10 +08:00
Johnny 71181b1640 chore: update openapi version 2025-07-20 12:02:16 +08:00
Huang Cheng Ting f675324994 chore: update zh-Hant translation (#4895) 2025-07-18 19:27:03 +08:00
Steven d7ced7b738 fix: code block style in dark mode 2025-07-18 19:25:29 +08:00
Johnny 74769b3332 fix: user state 2025-07-17 22:36:28 +08:00
Johnny e3735d2de3 fix: storage setting 2025-07-17 22:02:40 +08:00
Johnny f09897e4b6 fix: dialog state 2025-07-17 21:58:00 +08:00
Huang Cheng Ting 6119a4b965 chore: update zh-Hant translation (#4889) 2025-07-17 21:24:29 +08:00
Maximilian Krauß c4baba8527 fix(syntax-highlighting): adds missing CSS imports to CodeBlock.tsx (#4890) 2025-07-17 21:23:42 +08:00
Anthony Cooper 1f88e3e2d2 chore: Docker hyperlink in README (#4887) 2025-07-17 12:12:48 +08:00
Johnny 40130350c5 fix: args offset for postgres 2025-07-17 00:05:07 +08:00
Steven 834f92f67c chore: fix linter 2025-07-16 22:24:50 +08:00
Steven 0398df1d21 chore: update migrator comments 2025-07-16 21:59:37 +08:00
Jovane Castro a8db132110 chore(i18n): update hindi translation (#4858) 2025-07-16 21:46:18 +08:00
XIN_____ 84eacebfbb chore: update zh text i18n (#4844) 2025-07-16 21:46:09 +08:00
Jovane Castro 72b5186a56 chore(i18n): update croatian translation (#4859) 2025-07-16 21:45:58 +08:00
Steven 54e6ca37a2 chore: tweak props definition 2025-07-15 23:51:28 +08:00
Steven 8df0dea304 chore: remove fixed theme color 2025-07-15 23:26:07 +08:00
Jovane Castro 7683b26658 chore(i18n): update farsi translation (#4855) 2025-07-15 23:21:16 +08:00
Jovane Castro 4066af989c chore(i18n): update spanish translation (#4854) 2025-07-15 23:20:52 +08:00
Jovane Castro 8ef13468c7 chore(i18n): update hungarian translation (#4860) 2025-07-15 23:20:15 +08:00
Jovane Castro 2d4b5a1044 chore(i18n): update german translation (#4853) 2025-07-15 19:25:33 +08:00
Jovane Castro a21112427b chore(i18n): update french translation (#4856) 2025-07-15 19:25:21 +08:00
Jovane Castro 5a53f7178c chore(i18n): update italian translation (#4861) 2025-07-15 19:25:10 +08:00
Jovane Castro 74d35f7e33 chore(i18n): update japanese translation (#4862) 2025-07-15 19:24:59 +08:00
Jovane Castro 163038d5e0 chore(i18n): update georgian translation (#4863) 2025-07-15 19:24:49 +08:00
Jovane Castro af60f81f96 chore(i18n): update korean translation (#4864) 2025-07-15 18:15:25 +08:00
Jovane Castro c79b114972 chore(i18n): update marathi translation (#4865) 2025-07-15 18:14:41 +08:00
Jovane Castro a95104a0d4 chore(i18n): update norwegian translation (#4866) 2025-07-15 18:14:30 +08:00
Jovane Castro ff38347272 chore(i18n): update dutch translation (#4867) 2025-07-15 18:14:19 +08:00
Jovane Castro 4659b932d0 chore(i18n): update polish translation (#4868) 2025-07-15 18:14:09 +08:00
Jovane Castro d9e13baa37 chore(i18n): update portuguese-Brazil translation (#4869) 2025-07-15 18:13:58 +08:00
Jovane Castro 4551a0c52d chore(i18n): update portuguese translation (#4870) 2025-07-15 18:13:40 +08:00
Jovane Castro bd1f675051 chore(i18n): update slovenian translation (#4871) 2025-07-15 18:13:19 +08:00
Jovane Castro b4046f339e chore(i18n): update swedish translation (#4872) 2025-07-15 18:12:56 +08:00
Jovane Castro d9d63bf174 chore(i18n): update thai translation (#4873) 2025-07-14 23:26:17 +08:00
Jovane Castro d2dcf26104 chore(i18n): update turkish translation (#4874) 2025-07-14 23:26:06 +08:00
Johnny 1c408ff5a9 chore: remove unused main file 2025-07-14 23:18:24 +08:00
Jovane Castro 78387bec83 chore(i18n): update ukrainian translation (#4875) 2025-07-14 23:14:06 +08:00
Dedy F. Setyawan def61a8877 fix(i18n): Improve Indonesian translation (#4849) 2025-07-12 21:29:51 +08:00
Anthony Cooper 02641ef10a chore: hyperlinks in README Prerequisites (#4848) 2025-07-12 21:29:34 +08:00
unuunn 08883b58a7 updated Russian translation (#4840) 2025-07-10 07:38:56 +08:00
unuunn 9eafb9bc26 feat: highlight pinned memos (#4843) 2025-07-10 07:38:33 +08:00
unuunn 452f47c4b9 set HasCode only for CodeBlock (#4842) 2025-07-10 07:37:33 +08:00
Steven 29b683d5db fix: dialog styles 2025-07-09 21:48:02 +08:00
Steven e8862e3ca9 chore: update claude.md 2025-07-09 21:13:54 +08:00
Amar Singh Rathour b779dd2e54 fix: correct avatar URL generation to resolve 404 errors (#4839) 2025-07-09 21:05:52 +08:00
Dedy F. Setyawan e803d7bc0f feat(i18n): update Indonesian (id) translations (#4838) 2025-07-09 18:08:36 +08:00
unuunn 8732575ea4 fix: dayjs - ISO 8601 compatible DATE_TIME_FORMAT (#4829) 2025-07-09 00:16:10 +08:00
XIN_____ 0b1b471ee4 chore: update zh-Hant.json (#4833) 2025-07-08 23:03:35 +08:00
Steven 3ac4a03229 chore: update i18n 2025-07-08 20:33:44 +08:00
Steven c1708df7a2 chore: use select/dropdown instead of popover 2025-07-08 20:25:56 +08:00
Jovane Castro d32924ec48 chore: update i18n for Arabic locale (#4825) 2025-07-08 19:57:50 +08:00
Jovane Castro 1e582baf1c chore: update i18n for Catalan locale (#4826) 2025-07-08 19:57:14 +08:00
Jovane Castro eeb18e5deb chore: update i18n for Czech locale (#4827) 2025-07-08 19:57:08 +08:00
Kevin b074aefc34 chore: enhance site.webmanifest in firefox (#4828)
Signed-off-by: Kevin <16837578+KevinStaude@users.noreply.github.com>
2025-07-08 19:56:46 +08:00
Steven 533591af2b chore: theme in user setting 2025-07-08 19:50:04 +08:00
Johnny f907619752 chore: move frontend store 2025-07-07 22:44:08 +08:00
Johnny 12fdf5292d chore: tweak form style 2025-07-07 22:33:49 +08:00
johnnyjoy 239671eb87 chore: tweak tag style 2025-07-07 22:20:17 +08:00
Johnny e55ed8a9c7 chore: new theme whitewall 2025-07-07 20:13:55 +08:00
Johnny 1b3083b216 feat: themes (#4824) 2025-07-07 20:13:22 +08:00
Johnny 3426a791b6 chore: update tag styles 2025-07-07 08:58:09 +08:00
Johnny fb13d2e63d chore: tweak colors 2025-07-07 08:46:53 +08:00
Johnny d8d88c2505 fix: creator view 2025-07-06 22:51:28 +08:00
Johnny f2e27c16a1 chore: tweak colors 2025-07-06 22:26:54 +08:00
Johnny 240d89fbca feat: migrate dialogs 2025-07-06 22:01:55 +08:00
Jovane Castro f70138535c chore: update i18n for pt-BR text (#4819) 2025-07-06 13:59:50 +08:00
Johnny 35928ce5ba chore: unify colors 2025-07-06 13:55:08 +08:00
Jovane Castro 2e474d37fd chore: update i18n for pt-BR locale (#4817) 2025-07-05 19:32:57 +08:00
dependabot[bot] d60aee7823 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.80.0 to 1.82.0 (#4806)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-05 19:32:25 +08:00
Johnny 41fdc7a484 chore: fix frontend linter 2025-07-05 11:44:01 +08:00
Johnny a3de61a141 chore: fix dark mode 2025-07-05 11:40:49 +08:00
XIN_____ cf16795a98 chore: update zh text (#4797) 2025-07-05 11:28:30 +08:00
dependabot[bot] 3c512939a8 chore: bump github.com/go-sql-driver/mysql from 1.9.2 to 1.9.3 (#4807)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-05 11:27:57 +08:00
Johnny db4b1f5fde chore: tweak styles 2025-07-05 11:26:59 +08:00
Johnny 91be2f68d1 feat: variant colors (#4816) 2025-07-04 23:03:13 +08:00
dependabot[bot] b164c15976 chore: bump @types/node from 22.15.34 to 24.0.8 in /web (#4802)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:55:35 +08:00
dependabot[bot] f8fa0985fb chore: bump tailwind-merge from 2.6.0 to 3.3.1 in /web (#4801)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:39:25 +08:00
dependabot[bot] 1e09bf9a4f chore: bump vite from 6.3.5 to 7.0.0 in /web (#4805)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:39:10 +08:00
dependabot[bot] 17cd19588d chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.77 to 1.17.82 (#4808)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:34:19 +08:00
dependabot[bot] 49004f230f chore: bump golang.org/x/mod from 0.24.0 to 0.25.0 (#4809)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:34:11 +08:00
Steven fda19c2d73 chore: update 2025-07-03 22:33:31 +08:00
Steven 046c6c83e1 chore: fix linter formats 2025-07-03 22:28:45 +08:00
Copilot e3a2dadb4b fix: tag count regression - remove double increment causing off-by-one error (#4800)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2025-07-02 20:17:19 +08:00
Steven 0df3171b64 chore: remove command 2025-07-01 20:14:42 +08:00
boojack 0cabdbe020 chore: rename Popover.tsx to popover.tsx
Signed-off-by: boojack <stevenlgtm@gmail.com>
2025-07-01 19:43:46 +08:00
Steven 49766ed920 chore: update frontend instructions 2025-07-01 19:42:25 +08:00
Johnny 493832aeb4 refactor: unify components 2025-07-01 19:29:48 +08:00
Steven 50a41a39a6 chore: tweak instructions 2025-06-30 19:49:18 +08:00
XIN_____ 98d1238674 chore: update i18n text for zh-hans (#4790) 2025-06-28 16:06:32 +08:00
Steven c18d6927ba chore: update user session table 2025-06-27 00:00:06 +08:00
johnnyjoy 1fffc41f79 feat: sliding expiration for user sessions 2025-06-26 23:03:28 +08:00
XIN_____ e93d695aa8 chore: update i18n for zh text (#4785)
* Update zh-Hans.json

* Update zh-Hant.json

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>
2025-06-26 08:44:32 +08:00
Johnny 3e24f8cf62 fix: seed data 2025-06-25 10:07:24 +08:00
Steven 42d1650c6d chore: tweak auth service 2025-06-24 23:31:37 +08:00
Steven 6e1b01cb68 chore: bump version 2025-06-24 23:06:57 +08:00
XIN_____ 3a7995c733 chore: update i18n text for zh-hans and zh-hant (#4784)
chore: update i18n text for zh-hant
2025-06-24 21:59:03 +08:00
johnnyjoy 976bd332fe chore: fix linter 2025-06-24 21:55:27 +08:00
johnnyjoy d6a75bba4c refactor: webhook service 2025-06-24 21:28:21 +08:00
jinjingroad 03399a6007 refactor: use the built-in max/min to simplify the code (#4781)
Signed-off-by: jinjingroad <jinjingroad@sina.com>
2025-06-24 07:12:02 +08:00
Johnny e6e460493c refactor: general user setting 2025-06-23 23:23:57 +08:00
Johnny 9b15936873 refactor: clean unused fields 2025-06-23 22:55:14 +08:00
Johnny 778a5eb184 refactor: memo filter 2025-06-23 22:38:44 +08:00
Johnny 52a5ca2ef4 chore: update get attachment binary 2025-06-23 21:20:59 +08:00
Steven 697e54758d fix: frontend linter 2025-06-23 21:20:37 +08:00
Steven 83febf9928 chore: clean resource definition 2025-06-23 21:08:25 +08:00
Steven 5821bb7a65 chore: update auth service 2025-06-23 20:31:18 +08:00
Steven 59eae4465a chore: update user session section 2025-06-23 20:12:29 +08:00
Johnny b8a37c7229 chore: fix linter 2025-06-23 09:27:06 +08:00
XIN_____ bbd984a754 chore: update i18n for zh (#4780)
* feat: add i18n text for zh

* feat: add i18n text for zh-hant
2025-06-23 09:14:49 +08:00
Johnny 4e3a4e36f6 feat: implement user sessions 2025-06-23 09:13:51 +08:00
Johnny 6e4d1d9100 fix: auth context 2025-06-22 22:58:00 +08:00
johnnyjoy 45df653f37 fix: navigation overflow style 2025-06-22 18:49:12 +08:00
Johnny a2bfa82a88 fix: linter 2025-06-22 14:13:27 +08:00
Johnny 77b7fc4441 feat: implement user session 2025-06-22 12:46:13 +08:00
Johnny 741fe35c2a refactor: rename session methods in auth service 2025-06-21 00:00:58 +08:00
Johnny cb96d4e76d fix: embedded attachment 2025-06-18 23:10:41 +08:00
Steven df52bf5e63 fix: tag count 2025-06-18 22:49:03 +08:00
Steven 35df62a96c chore: remove duplicated prefix from enums 2025-06-18 22:40:54 +08:00
XIN_____ d27639f147 chore: update i18n zh-Hans and zh-Hant (#4778)
* Update zh-Hans.json

* Update zh-Hant.json

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: @kiss-fire <iamtaoxin@gmail.com>
2025-06-18 20:46:37 +08:00
Steven d71fd2f84a refactor: auth service 2025-06-18 20:25:46 +08:00
Steven 9972a77d9e refactor: memo service 2025-06-18 19:58:38 +08:00
Steven 91c2a4cef9 refactor: inbox service 2025-06-18 19:06:09 +08:00
Steven a4920d464b refactor: attachment service part2 2025-06-18 00:09:19 +08:00
Steven bb5809cae4 refactor: attachment service 2025-06-17 22:15:19 +08:00
Steven 174b1a0361 chore: fix linter 2025-06-17 21:04:28 +08:00
Steven 760c164328 chore: add server tests 2025-06-17 20:56:10 +08:00
Steven f6e5da4499 refator: activity service 2025-06-17 09:00:03 +08:00
Steven 4a20b529df chore: add CLAUDE.md 2025-06-17 08:51:43 +08:00
Steven 8e8e246ab2 chore: add server tests 2025-06-17 00:29:42 +08:00
Steven dac059a7f7 refactor: identity provider service 2025-06-16 23:56:28 +08:00
Steven 8d8e9b3b30 refactor: shortcut service 2025-06-16 23:10:50 +08:00
Steven 1ea4cc453c refactor: workspace setting service 2025-06-16 22:51:26 +08:00
Steven da906c665c chore: tweak workspace service 2025-06-16 22:20:10 +08:00
Steven 3b0c87591f refactor: webhook service 2025-06-16 22:10:43 +08:00
Steven c9ab03e1a0 refactor: user service 2025-06-16 21:49:38 +08:00
Steven 330282d8b2 chore: tweak styles 2025-06-16 20:48:08 +08:00
Johnny f467264e7d chore: remove memopayload runonce 2025-06-16 20:24:57 +08:00
Johnny 38b6c3afb9 chore: fix linter 2025-06-15 10:27:24 +08:00
Johnny 3fd29f6493 refactor: schema migrator 2025-06-15 10:23:18 +08:00
XIN_____ d386b83b7b chore: update i18n text for zh (#4771)
* feat: add i18n text

* feat: add i18n text for zh
2025-06-12 23:09:04 +08:00
Steven c9c07a599c chore: unify action names 2025-06-11 23:39:29 +08:00
Steven efc0dc9aea chore: update trim in Autocomplete 2025-06-11 23:21:48 +08:00
Johnny acb71dfb69 chore: tweak button styles 2025-06-10 22:51:42 +08:00
KidLoveToPlay df8d1d4f3d fix: trim queryText and split by regex (#4766) 2025-06-09 22:13:39 +08:00
Johnny f2a01d9ccb chore: use popover instead of dropdown/menu 2025-06-08 23:21:23 +08:00
Johnny 522da2a114 fix: border color 2025-06-08 00:39:51 +08:00
Johnny f5c64849d2 chore: upgrade tailwindcss to v4 2025-06-07 10:15:12 +08:00
Ezmana a50253d311 chore: add missing lines and French translations (#4761)
Adding missing lines and translations
2025-06-06 19:18:48 +08:00
Steven add099b89d chore: update rollup options 2025-06-05 23:09:15 +08:00
Steven 786c6f672e chore: remove prevent default for enter keydown 2025-06-05 23:08:55 +08:00
boojack cc36422e43 chore: tweak README.md 2025-06-05 09:43:41 +08:00
Steven fe71b01f2d chore: polish readme 2025-06-04 23:10:31 +08:00
johnnyjoy c84dcddbf6 chore: always show visibility label 2025-06-04 22:05:51 +08:00
johnnyjoy 8d9396247b fix: external newline 2025-06-04 21:28:58 +08:00
Maya Doshi efb8e7ab0c fix: broken resource urls in RSS feed (#4753)
fix: resource url generation in rss feed
2025-06-04 09:06:34 +08:00
johnnyjoy 94d1e20570 chore: update date time format 2025-06-03 21:22:14 +08:00
Steven 6d319900d6 fix: date format 2025-06-03 09:24:38 +08:00
Johnny b942643785 chore: tweak seed data 2025-06-02 20:06:45 +08:00
Lincoln Nogueira 44e710ce4a fix: downgrade modernc.org/libc to v1.65.7 (#4745)
`modernc.org/libc` version on go.mod must match whatever is on `modernc.org/sqlite`'s [go.mod](https://gitlab.com/cznic/sqlite/-/blob/v1.37.1/go.mod#L9) file to prevent sqlite-related issues.

See:
  - <https://pkg.go.dev/modernc.org/sqlite#hdr-Fragile_modernc_org_libc_dependency>
  - <https://gitlab.com/cznic/sqlite/-/issues/177>
2025-06-02 18:19:57 +08:00
Johnny d20362e722 chore: tweak stat card 2025-06-02 10:20:11 +08:00
Johnny 1594c1ce3e chore: bump version 2025-06-02 09:39:57 +08:00
Johnny 3343dc73f7 chore: update navigator 2025-06-02 09:39:50 +08:00
Johnny 663e56747f chore: replace switch kit 2025-06-02 01:01:29 +08:00
Johnny ff0f275431 chore: fix golangci-lint version 2025-06-02 00:34:45 +08:00
dependabot[bot] 136c1d7aa6 chore: bump golangci/golangci-lint-action from 7 to 8 (#4744)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 7 to 8.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v7...v8)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 00:32:53 +08:00
dependabot[bot] 7c9215b513 chore: bump i18next from 24.2.3 to 25.2.1 in /web (#4742)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.3 to 25.2.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.3...v25.2.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 25.2.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 00:32:27 +08:00
Johnny d4425a6aa1 chore: upgrade dependencies 2025-06-02 00:27:35 +08:00
Johnny e6fe088ac0 chore: fix missing observer 2025-06-01 09:22:33 +08:00
Johnny fd99e10962 chore: tweak sidebar 2025-06-01 09:13:44 +08:00
Johnny 2595e32f83 chore: simplify date editor 2025-05-31 11:14:47 +08:00
Johnny 673026ffa1 chore: update statistics view 2025-05-31 09:43:24 +08:00
Johnny 376b25a69c chore: fix visibility selector style (#4733) 2025-05-31 09:15:28 +08:00
Steven f1b365f928 refactor: clean packages 2025-05-29 21:44:43 +08:00
Johnny 2bde296217 chore: add demo deployment to Render action 2025-05-29 08:38:01 +08:00
Johnny ea4e7a1606 refactor: memo editor (#4730) 2025-05-29 07:46:40 +08:00
Maximilian Krauß 77d3853f73 fix: inherits memo visibility for default comment visibility (#4728) 2025-05-28 22:18:41 +08:00
Steven a317f9e653 fix: linter 2025-05-28 21:21:27 +08:00
Steven de3e55c2e6 feat: support now() time functions 2025-05-28 21:18:49 +08:00
Steven f5ecb66fb8 feat: implement height-based masonry view 2025-05-28 08:27:15 +08:00
Steven 8520e30721 fix: handle type assertion safely 2025-05-27 23:44:39 +08:00
Steven ef6f80d925 chore: fix linter 2025-05-27 23:22:32 +08:00
Steven 81ae42518e chore: fix linter 2025-05-27 22:49:56 +08:00
Maximilian Krauß eca91d5c0c feat(rss): use server title and description for RSS feed, if configured (#4717) 2025-05-27 22:10:23 +08:00
Steven ad2c5f0d05 refactor: store cache 2025-05-27 22:06:41 +08:00
Steven c23aebd648 refactor: memo filter store 2025-05-27 21:14:18 +08:00
Steven f12d7ae8bc chore: add asynchronous webhook dispatch 2025-05-27 20:01:04 +08:00
Jonathan Fok kan 7c05a9b997 fix(editor): prevent race condition and ensure correct list continuation on Enter (#4716)
* fix(editor): Prevent race condition and ensure correct list continuation on Enter

_

* fix: always insert newline after preventing default Enter key behavior
2025-05-27 19:57:33 +08:00
Johnny d76f988bb5 fix: edit for comment 2025-05-27 08:38:14 +08:00
Steven 785c250f3c refactor: migrate memo store 2025-05-27 08:26:13 +08:00
Steven dcd68bc5f4 refactor: migrate resource store to v2 2025-05-27 07:55:00 +08:00
Steven 46900f9807 refactor: move store prefixes to common module 2025-05-27 07:49:46 +08:00
Steven 46be6b0ff6 fix: missing service handler 2025-05-26 23:22:10 +08:00
Steven b89d8f5342 feat: implement hasTaskList filter 2025-05-26 22:37:59 +08:00
Steven cbf5687dd9 chore: remove unused action 2025-05-26 21:50:36 +08:00
eya46 4924b23884 fix: state mismatch in Storage and System pages (#4719)
* fix: sync storage setting state

* fix: sync customProfile state
2025-05-26 21:50:10 +08:00
Steven 64b27d5a4e refactor: shortcut service 2025-05-26 21:45:14 +08:00
dabeeduu 6964c1df05 fix: make the save button disabled after a successful update (#4721)
* fix: make the save button disabled after a successful update

* fix: fixing formatting error

---------

Co-authored-by: didi <didi@localhost.localdomain>
2025-05-26 14:50:13 +08:00
Brian c6e6b7b93b feat: add infinite scrolling for memos (#4715)
* feat(WIP): add prop-driven infinite scroll

* feat(WIP): add global toggle for infinite scrolling under settings

* feat: integrate newly added scroll-mode selection state with backend for persists across refreshes

* fix: default to infinite scrolling over load more button & remove redundant setting option

* fix: rectify linting issues

* Update web/src/components/PagedMemoList/PagedMemoList.tsx

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-05-25 23:12:47 +08:00
Steven 46d5307d7f fix: prevent XSS for specific content types 2025-05-22 00:05:33 +08:00
Dimitris Zervas c2528c57f0 feat: automatically add a new table row in the editor when pressing enter (#4706)
Automatically add a new table row in the editor when pressing enter
2025-05-21 20:11:53 +08:00
Steven 72babbb393 fix: dark mode of highlight.js 2025-05-20 23:58:22 +08:00
johnnyjoy f9c0621c15 refactor: root layout 2025-05-19 22:15:11 +08:00
johnnyjoy ee99afd7a4 chore: enable location by default 2025-05-19 21:25:51 +08:00
Johnny d4ebf293f3 chore: fix format 2025-05-19 10:03:05 +08:00
Jake Howard 0440888571 chore: hide "or" when password auth disabled (#4699)
This makes the UI cleaner, instead only showing the "Sign in with ..." buttons.
2025-05-19 09:59:52 +08:00
Steven 606924b4c9 chore: unify form styles 2025-05-15 22:15:01 +08:00
johnnyjoy f9e07a2245 feat: support update user's role 2025-05-15 19:36:15 +08:00
Simon ead2d70082 fix: remove duplicated “Enable” in settings label (#4692)
remove duplicated “Enable” in settings label
2025-05-15 15:08:50 +08:00
Steven 1f79ee575b fix: create user with avatar url for sqlite 2025-05-14 23:45:02 +08:00
johnnyjoy 21935abe3f chore: update canary build action 2025-05-14 22:24:54 +08:00
johnnyjoy ca79990679 refactor: merge sign in requests 2025-05-14 22:13:52 +08:00
johnnyjoy a0f68895ab chore: add more logs for oauth2 2025-05-14 20:38:14 +08:00
johnnyjoy 733f16816b chore: bump mui 2025-05-13 23:28:15 +08:00
johnnyjoy 43d176f272 fix: idp config convert 2025-05-13 20:40:54 +08:00
johnnyjoy 966a108d52 chore: check signin with sso 2025-05-13 20:36:00 +08:00
Steven fa1ad7dc72 chore: update list padding 2025-05-12 22:39:25 +08:00
啥也不会的帆 f6054b6138 fix: preview image window proportion error (#4689) 2025-05-12 21:32:01 +08:00
Johnny 87798801fc fix: list styles 2025-05-12 09:09:09 +08:00
johnnyjoy 446447a20c chore: update stable build action 2025-05-11 18:04:15 +08:00
Pavel Stržínek 070b392942 chore: Czech locale update (#4685)
* cs locale updated

* cs locale update
2025-05-11 17:45:32 +08:00
Johnny 9c7899781f chore: update alt text of deepwiki badge 2025-05-09 14:58:58 +08:00
johnnyjoy cd5abd9e60 chore: update nsfw description 2025-05-08 21:18:46 +08:00
johnnyjoy ccfa9983e9 fix: user avatar url 2025-05-08 20:28:00 +08:00
mousemin 30f37f6a05 feat: enhance site.webmanifest in chrome (#4676)
Update site.webmanifest
2025-05-07 22:47:55 +08:00
Sergey Gorbunov e23ade1f8b feat: support listening on a UNIX socket (#4654) 2025-05-07 22:12:05 +08:00
johnnyjoy 2a92baf52c fix: filter args of postgres 2025-05-06 21:19:13 +08:00
Johnny 1328e0b861 chore: remove issue-translator 2025-05-03 16:16:01 +08:00
dependabot[bot] c3273f8f97 chore: bump @vitejs/plugin-legacy from 6.0.2 to 6.1.1 in /web (#4661)
Bumps [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/HEAD/packages/plugin-legacy) from 6.0.2 to 6.1.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/plugin-legacy/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.1.1/packages/plugin-legacy)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-legacy"
  dependency-version: 6.1.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:15:21 +08:00
dependabot[bot] 24650140b2 chore: bump @types/node from 22.13.10 to 22.15.3 in /web (#4660)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.10 to 22.15.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:10:17 +08:00
dependabot[bot] f6b5b26cda chore: bump eslint from 9.23.0 to 9.25.1 in /web (#4663)
Bumps [eslint](https://github.com/eslint/eslint) from 9.23.0 to 9.25.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.23.0...v9.25.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.25.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 16:10:08 +08:00
dependabot[bot] 0ab7082c7c chore: bump mobx from 6.13.6 to 6.13.7 in /web (#4662)
Bumps [mobx](https://github.com/mobxjs/mobx) from 6.13.6 to 6.13.7.
- [Release notes](https://github.com/mobxjs/mobx/releases)
- [Commits](https://github.com/mobxjs/mobx/compare/mobx@6.13.6...mobx@6.13.7)

---
updated-dependencies:
- dependency-name: mobx
  dependency-version: 6.13.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:27:06 +08:00
dependabot[bot] 8550176cfa chore: bump golang.org/x/crypto from 0.35.0 to 0.37.0 (#4665)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.35.0 to 0.37.0.
- [Commits](https://github.com/golang/crypto/compare/v0.35.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:26:28 +08:00
dependabot[bot] fdcef4d3a7 chore: bump golang.org/x/net from 0.35.0 to 0.39.0 (#4666)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.35.0 to 0.39.0.
- [Commits](https://github.com/golang/net/compare/v0.35.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:26:19 +08:00
dependabot[bot] a266c4c6a5 chore: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 (#4667)
Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.1 to 5.2.2.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.1...v5.2.2)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-version: 5.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:17:07 +08:00
dependabot[bot] 0c692c48af chore: bump modernc.org/sqlite from 1.36.0 to 1.37.0 (#4668)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.36.0 to 1.37.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.36.0...v1.37.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:16:59 +08:00
dependabot[bot] b5f68576ff chore: bump golang.org/x/mod from 0.23.0 to 0.24.0 (#4669)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/mod/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-03 14:16:51 +08:00
boojack 75f5c4c0b2 chore: add deepwiki badge 2025-04-28 13:51:41 +08:00
João Tiago a46301fa77 feat: support child tags in NSFW blur feature (#4640)
* fix: add support for child nsfw tags

* fix: correctly detect child tags of custom NSFW tags

* Update web/src/components/MemoView.tsx

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-04-26 16:23:15 +08:00
johnnyjoy 411a91122b fix: linter error 2025-04-24 10:11:35 +08:00
johnnyjoy eb33a604b2 feat: support mapping avatar url from oauth2 2025-04-24 10:07:24 +08:00
Steven e41916408a chore: update dockerfile 2025-04-21 22:26:18 +08:00
Johnny 0f965c6fe0 chore: add action cache 2025-04-21 21:39:09 +08:00
Johnny 33907539cd chore: merge release action 2025-04-21 21:26:46 +08:00
johnnyjoy dc5f37ebba chore: remove unused demo dockfile 2025-04-21 21:16:38 +08:00
Johnny 7e1368028b chore: add dockerfile.demo 2025-04-21 09:02:38 +08:00
Johnny fdc0553cfb chore: move frontend build to action 2025-04-19 23:10:32 +08:00
Simon bb892be5b3 feat: improve visual feedback in MemoEditor for drag/drop file uploads (#4634)
* improve drag/drop file upload UI

* fix eslint errors

* use tailwind for cursor styles

* fix eslint issues
2025-04-18 23:49:59 +08:00
Johnny d38f4699c2 chore: try build arm/v7 2025-04-17 23:28:33 +08:00
Steven 1a121e350b chore: update gitignore 2025-04-17 23:11:36 +08:00
RichardYe 76ed1b5cc5 feat: set locale based on browser language when user is not logged in (#4635)
* feat: set locale based on browser language when user is not logged in

* docs: comments for locale fallback logic
2025-04-17 20:02:41 +08:00
Steven f6e4e504fe chore: remove armv7 2025-04-16 23:05:27 +08:00
Steven aa272670ce chore: upgrade buf 2025-04-16 23:00:11 +08:00
Steven 7475a30fe9 chore: update docker platforms 2025-04-16 22:50:31 +08:00
Steven e2f5c61e30 fix: docker username in actions 2025-04-16 22:39:58 +08:00
Steven 02f8e0da41 chore: update actions 2025-04-16 22:39:15 +08:00
RichardYe ebccef6033 fix: shutdown gRPC server gracefully (#4626)
fix: add graceful shutdown for gRPC server
2025-04-15 22:58:25 +00:00
Steven 789a9cc5a2 fix: padding left of list 2025-04-14 23:00:36 +08:00
Steven a6be658f42 fix: list memo comments 2025-04-14 22:51:11 +08:00
Johnny b94682dc4f chore: fix linter 2025-04-12 22:16:32 +08:00
Johnny 18b9b9d18f chore: implement memo filter in list memo relations 2025-04-12 22:13:18 +08:00
Johnny 08f9b18ced fix: list memo relations 2025-04-12 22:02:13 +08:00
Johnny 2f6dc2b51f fix: padding of list 2025-04-10 23:06:14 +08:00
Johnny 7632c52c0c chore: bump version 2025-04-10 22:52:03 +08:00
Johnny 97b23f46e6 chore: remove resource title 2025-04-09 22:58:53 +08:00
倒霉狐狸 ebf13c4dff chore: caching resource files accelerates second requests (#4614)
* cache assets files

* Apply suggestions from code review

* Update server/router/frontend/frontend.go

* Update server/router/frontend/frontend.go

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-04-09 22:22:03 +08:00
Johnny 3cc0e255ce fix: memo filter for postgres 2025-04-08 23:46:08 +08:00
Johnny f5d5ebea6f chore: hide actions for comment 2025-04-06 22:58:43 +08:00
Johnny aa8cf44c41 chore: fix entrypoint.sh 2025-04-06 22:44:19 +08:00
Johnny 9dde9f332f chore: move dockerfile 2025-04-06 22:40:26 +08:00
dependabot[bot] 052d5d41fe chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.26.1 to 2.26.3 (#4586)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.26.1 to 2.26.3.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.26.1...v2.26.3)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:08:48 +08:00
dependabot[bot] bec0acc66a chore: bump golang.org/x/oauth2 from 0.27.0 to 0.28.0 (#4587)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.27.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 22:56:28 +08:00
Steven 3d610a78f2 chore: update golangci config 2025-04-02 22:53:17 +08:00
Steven ec17c4b015 chore: update linter ci 2025-04-02 22:51:22 +08:00
Steven 2cf2126d64 fix: golangci config 2025-04-02 22:47:34 +08:00
Steven 2aca8180d1 chore: update golangci config 2025-04-02 22:16:05 +08:00
Steven 0430de8713 chore: fix golangci version 2025-04-02 22:10:19 +08:00
dependabot[bot] 76737b5542 chore: bump golangci/golangci-lint-action from 6 to 7 (#4584)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6 to 7.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:17:02 +08:00
dependabot[bot] 39f85e9d68 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.64 to 1.17.70 (#4585)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.64 to 1.17.70.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.64...feature/s3/manager/v1.17.70)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:49 +08:00
dependabot[bot] ebc2cc2970 chore: bump google.golang.org/grpc from 1.70.0 to 1.71.1 (#4588)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.70.0 to 1.71.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:27 +08:00
dependabot[bot] d1fb602988 chore: bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#4589)
Bumps google.golang.org/protobuf from 1.36.5 to 1.36.6.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:16:11 +08:00
dependabot[bot] c43762a9b6 chore: bump lucide-react from 0.453.0 to 0.486.0 in /web (#4590)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.453.0 to 0.486.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.486.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:58 +08:00
dependabot[bot] 28074c1404 chore: bump nice-grpc-web from 3.3.6 to 3.3.7 in /web (#4591)
Bumps [nice-grpc-web](https://github.com/deeplay-io/nice-grpc) from 3.3.6 to 3.3.7.
- [Release notes](https://github.com/deeplay-io/nice-grpc/releases)
- [Commits](https://github.com/deeplay-io/nice-grpc/compare/nice-grpc-web@3.3.6...nice-grpc-web@3.3.7)

---
updated-dependencies:
- dependency-name: nice-grpc-web
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:46 +08:00
dependabot[bot] 2458bc98f2 chore: bump i18next from 24.2.2 to 24.2.3 in /web (#4592)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.2 to 24.2.3.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.2...v24.2.3)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:15:03 +08:00
dependabot[bot] d98520acba chore: bump @trivago/prettier-plugin-sort-imports from 4.3.0 to 5.2.2 in /web (#4593)
chore: bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.3.0 to 5.2.2.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.3.0...v5.2.2)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:14:46 +08:00
dependabot[bot] 3dac75f48c chore: bump react-datepicker from 7.6.0 to 8.2.1 in /web (#4594)
Bumps [react-datepicker](https://github.com/Hacker0x01/react-datepicker) from 7.6.0 to 8.2.1.
- [Release notes](https://github.com/Hacker0x01/react-datepicker/releases)
- [Commits](https://github.com/Hacker0x01/react-datepicker/compare/v7.6.0...v8.2.1)

---
updated-dependencies:
- dependency-name: react-datepicker
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 09:44:20 +08:00
Steven 4f39e00868 chore: fix lint 2025-04-01 20:06:54 +08:00
Johnny b770042a8a refactor: migrate eslint 2025-04-01 00:04:43 +08:00
cmuangs d649d326ef fix: remove errors.Wrap(nil) (#4576)
* Fix errors.Wrap(nil)

* fix resource_test failure where resource does not exist
2025-03-31 12:56:51 +08:00
Shawn 88b38ff2c0 fix: aws-chunked encoding is not supported with the specified x-amz-content-sha256 value for some s3 providers (#4575)
Co-authored-by: Shawn L. <shawn@sola.sh>
2025-03-31 08:49:48 +08:00
Johnny 09c50a8419 fix: codeblock highlight 2025-03-30 23:49:51 +08:00
johnnyjoy 8e6d9b4943 chore: buf generate 2025-03-30 13:16:42 +08:00
Anubhav Singh a63d9b471b feat: update ItalicNode to use repeated children instead of content (#4566)
* feat: update ItalicNode to use repeated children instead of content

* chore: update gomark dependency to latest version

---------

Co-authored-by: Anubhav Singh <anubhav@mail.techindika.com>
2025-03-28 16:15:03 +08:00
olavlan 8bdd1ec009 feat: add norwegian bokmål (nb) translation (#4561)
* add locale file for norwegian (nb)

* correct spelling
2025-03-27 13:14:12 +08:00
Anubhav Singh 194a49367c fix: incorrect checkbox state after removing checked items #4549 (#4552)
Co-authored-by: Anubhav Singh <anubhav@mail.techindika.com>
2025-03-25 21:59:30 +08:00
johnny 44df17aecc chore: bump version 2025-03-23 11:32:09 +08:00
Austin Pearce c4f094d22b fix: BrandBanner to use NavLink (#4536)
* Fix BrandBanner to use NavLink

* Apply suggestions from code review

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-03-18 21:18:22 +08:00
XIN_____ 3d0f7285f9 feat: add i18n for Pinned (#4535)
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-03-18 21:17:09 +08:00
Johnny d63ef81c9d chore: update common locale 2025-03-18 09:04:47 +08:00
Amir Ehsandar 7b23bdcfcf fix: allow admins to uncheck disallow password if applicable (#4532)
- closes #4469
2025-03-18 09:00:50 +08:00
Steven 9b957edd1f chore: fix linter 2025-03-17 21:52:35 +08:00
Steven 8164986fcc chore: move store test 2025-03-17 21:51:02 +08:00
Steven fdf9d9f506 chore: move resource name test 2025-03-17 21:41:21 +08:00
XIN_____ b79755dd09 feat: update zh-hans i18n (#4531)
* feat: update zh-hans i18n

* Update zh-Hans.json

Co-authored-by: taosin <xinxintao@foxmail.com>

---------

Co-authored-by: KissFire <53330905+kiss-fire@users.noreply.github.com>
2025-03-17 18:22:13 +08:00
Amir Ehsandar 2e9b9368db fix: prevent double effect on image modal wheel event (#4522)
- escape key closes the modal
- zooming is a bit smoother
2025-03-16 10:28:59 +08:00
Amir Ehsandar c0643ff6fa fix: use valid query parameters for postgres (#4515) 2025-03-15 12:59:00 +08:00
Steven 6b042fe16e chore: always show full content when pinned 2025-03-14 20:13:54 +08:00
Steven ea3a534ce5 chore: fix typo 2025-03-14 20:01:10 +08:00
Steven f1f0253e8d fix: typo 2025-03-14 19:55:25 +08:00
George Wu fae7b5d3e8 fix: typo s/contnet/content (#4507) 2025-03-14 14:54:55 +08:00
XIN_____ be18a7b77b chore: update i18n for resource page (#4505)
* chore: update i18n for resources

* Update Resources.tsx

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>
2025-03-14 13:04:07 +08:00
Amir Ehsandar 32c69bbb52 fix: user stats changes based on selected tab (#4504)
- set partial only the relevant user stats instead of only adding up stats
2025-03-14 13:02:47 +08:00
Amir Ehsandar e75ef0964d feat: implement grpc health service checking database connection (#4499) 2025-03-14 08:43:01 +08:00
Johnny fc7dc58720 chore: move archived route 2025-03-13 20:38:14 +08:00
Lincoln Nogueira e8e393a9cb chore(i18n): tidy (#4497)
- sort all keys alphabetically for easier side-by-side translation

- remove keys from other locales that don't exist anymore in `en.json`

- remove keys from other locales that have missing {{interpolations}}

- add missing entries to pt-BR
2025-03-13 20:37:50 +08:00
XIN_____ 1762496e79 chore: update zh-hans text for rename-tag (#4496)
* Update RenameTagDialog.tsx

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

* Update zh-Hans.json

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>

---------

Co-authored-by: kiss-fire <iamtaoxin@gmail.com>
2025-03-13 20:00:22 +08:00
Johnny 34ab88348e chore: sort by pinned 2025-03-13 19:57:12 +08:00
Johnny d794e6db76 chore: remove internal frontend cache 2025-03-13 11:23:27 +08:00
XIN_____ 81e40d9b18 chore: update i18n for tag reame (#4493)
* feat: update i18n for zh-hans

* Update zh-Hans.json

---------

Co-authored-by: KissFire <53330905+kiss-fire@users.noreply.github.com>
2025-03-13 09:20:46 +08:00
Johnny fc5962f6a4 feat: show pinned count 2025-03-12 23:33:51 +08:00
Johnny fb3c17d0e9 chore: update mobile header 2025-03-12 22:21:22 +08:00
Johnny 0dfcb1a7c8 feat: total memo count 2025-03-12 22:15:46 +08:00
Johnny 3349311b51 chore: update frontend dependencies 2025-03-12 21:05:32 +08:00
Heiko 775673d17f fix: update README.md (#4492)
Fixed link for contribution
2025-03-12 20:35:10 +08:00
XIN_____ 1edb9e6774 feat: update i18n for zh-hans (#4488)
* chore:memo filter support i18n for zh-hans

* feat: restore addFilter method value field in StatisticsView.tsx

* chore: change getFilterDisplayText for i18n

* chore: add string type in utils/i18n

* feat: using switch to avoid change TranslationType

* feat: eslint check

* feat: eslint fix
2025-03-12 16:54:04 +08:00
Simon 690f28bed8 feat: add loading spinner during file upload process (#4491)
* show LoaderIcon while uploading file

* fix spacing for eslint
2025-03-12 09:56:22 +08:00
Johnny 7a438be08d chore: update user stats 2025-03-12 09:14:43 +08:00
Johnny e3a4f49c5c feat: implement creator_id factor 2025-03-11 22:00:57 +08:00
Johnny ba52a786f9 chore: update canary image 2025-03-11 10:23:38 +08:00
wrrrzr b0392954f4 Add executable permission to scripts/build.sh (#4486) 2025-03-11 09:00:42 +08:00
Johnny 7123a2cf51 chore: remove sort by pinned 2025-03-10 21:32:17 +08:00
Johnny ff13e0f353 chore: add legacy plugin 2025-03-10 18:57:48 +08:00
Johnny 925e97882e feat: support pinned factor 2025-03-10 18:52:12 +08:00
Johnny 90119c1af8 refactor: move memo property 2025-03-07 22:53:35 +08:00
Johnny 3401def442 chore: simplify memo filters 2025-03-06 23:10:20 +08:00
Johnny 16a0872972 chore: enable auto compact by default 2025-03-06 23:02:12 +08:00
Johnny 56ad8ab3bd refactor: view store 2025-03-06 21:38:54 +08:00
Johnny 2e0467e3d1 fix: mobile header 2025-03-06 20:46:16 +08:00
Lincoln Nogueira d7d3568ba4 chore(i18n): update pt-BR (#4471) 2025-03-06 09:21:44 +08:00
Johnny c668073cf3 chore: update resource view 2025-03-05 23:08:44 +08:00
Johnny 92a44e26b9 chore: remove emoji regex 2025-03-04 22:56:46 +08:00
XIN_____ 6ed6b86a75 chore: update i18n zh-hans (#4467)
* Update MemoDisplaySettingMenu.tsx

Masonry View

* Update en.json

* Update zh-Hans.json
2025-03-04 22:43:48 +08:00
Johnny 36d458fe88 chore: update masonry scale 2025-03-03 22:41:18 +08:00
Johnny 7592e5fe76 fix: masonry state 2025-03-03 09:23:40 +08:00
Johnny d6be20b917 feat: implement masonry view 2025-03-02 23:27:12 +08:00
Johnny a8713ec639 chore: update backend dependencies 2025-03-02 21:58:46 +08:00
Johnny 32da704be6 chore: update frontend dependencies 2025-03-02 21:55:55 +08:00
dependabot[bot] 858053e3b1 chore: bump @dnd-kit/sortable from 8.0.0 to 10.0.0 in /web (#4454)
Bumps [@dnd-kit/sortable](https://github.com/clauderic/dnd-kit/tree/HEAD/packages/sortable) from 8.0.0 to 10.0.0.
- [Release notes](https://github.com/clauderic/dnd-kit/releases)
- [Changelog](https://github.com/clauderic/dnd-kit/blob/master/packages/sortable/CHANGELOG.md)
- [Commits](https://github.com/clauderic/dnd-kit/commits/@dnd-kit/sortable@10.0.0/packages/sortable)

---
updated-dependencies:
- dependency-name: "@dnd-kit/sortable"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:47:19 +08:00
dependabot[bot] b36e2b630a chore: bump @bufbuild/buf from 1.48.0 to 1.50.0 in /web (#4452)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.48.0 to 1.50.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.48.0...v1.50.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:47:09 +08:00
dependabot[bot] c24ad79b36 chore: bump vite from 6.0.6 to 6.2.0 in /web (#4451)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.6 to 6.2.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.2.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:59 +08:00
dependabot[bot] 9a0a1f0baf chore: bump i18next from 24.2.0 to 24.2.2 in /web (#4453)
Bumps [i18next](https://github.com/i18next/i18next) from 24.2.0 to 24.2.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v24.2.0...v24.2.2)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:50 +08:00
dependabot[bot] 8ab77442f5 chore: bump fuse.js from 7.0.0 to 7.1.0 in /web (#4455)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v7.0.0...v7.1.0)

---
updated-dependencies:
- dependency-name: fuse.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:25 +08:00
dependabot[bot] ea9db2ff56 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.48 to 1.17.61 (#4460)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.48 to 1.17.61.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.48...credentials/v1.17.61)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 17:46:12 +08:00
Johnny 8acded1f23 chore: fix linter 2025-03-02 15:40:16 +08:00
Johnny 372fc3655a refactor: retire less 2025-03-02 15:34:21 +08:00
dependabot[bot] 4ed6862423 chore: bump pnpm/action-setup from 4.0.0 to 4.1.0 (#4456)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:42 +08:00
dependabot[bot] 69ea9eac94 chore: bump google.golang.org/protobuf from 1.35.2 to 1.36.5 (#4458)
Bumps google.golang.org/protobuf from 1.35.2 to 1.36.5.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:30 +08:00
dependabot[bot] 459e8e9589 chore: bump modernc.org/sqlite from 1.34.2 to 1.36.0 (#4457)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.34.2 to 1.36.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.34.2...v1.36.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:17 +08:00
dependabot[bot] d107373ae9 chore: bump github.com/google/cel-go from 0.23.2 to 0.24.1 (#4459)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.23.2 to 0.24.1.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.23.2...v0.24.1)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:21:06 +08:00
dependabot[bot] 4e5b9d39b3 chore: bump github.com/spf13/cobra from 1.8.1 to 1.9.1 (#4461)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.9.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.1...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 12:20:50 +08:00
xt 7651c454fd chore: chinese localization enhancements (#4450)
* Chinese localization enhancements

* Fix for eslint

* Chinese localization fixed
2025-02-28 17:45:50 +08:00
Johnny 5562282822 chore: update demo site 2025-02-27 23:05:43 +08:00
Johnny 47b41bce85 refactor: move memo relation definition 2025-02-27 15:28:36 +08:00
Johnny ba98fddbaf chore: go mod tidy 2025-02-27 15:12:25 +08:00
Johnny 5bb4a300db chore: bump gomark 2025-02-27 15:10:39 +08:00
Johnny 012405f7fd refactor: user stats state 2025-02-26 22:58:22 +08:00
Johnny 81502d9092 fix: stats requests 2025-02-26 22:32:26 +08:00
Johnny b897b243e5 feat: dynamic fetch user stats 2025-02-26 22:29:59 +08:00
Johnny 5d1075a647 refactor: update home layout 2025-02-26 22:14:07 +08:00
Johnny 0da3859878 chore: bump version to 0.24.1 2025-02-26 21:41:57 +08:00
Johnny b56aa397b2 chore: update assets routes 2025-02-26 21:40:28 +08:00
Johnny f60906ce33 chore: tweak vite config 2025-02-26 21:21:46 +08:00
nbb 5962c6d04b feat: optimize initial load performance by implementing lazy loading and code splitting (#4445) 2025-02-26 13:16:05 +08:00
Johnny bef67638c1 chore: fix home route 2025-02-25 23:34:55 +08:00
Johnny 8e4e745ba9 chore: update navigation 2025-02-25 23:13:48 +08:00
XIN_____ 3a7b24bd01 chore: add cursor-pointer to memo's display time (#4441)
feat: memo title add cursor-pointer when mouse hover
2025-02-25 10:13:04 +08:00
Johnny 271a8c8c28 refactor: home layout 2025-02-24 23:42:35 +08:00
Johnny 9107a941ca chore: update linter config 2025-02-24 22:21:07 +08:00
Johnny f98c519834 fix: linter 2025-02-24 22:04:25 +08:00
Johnny 66a4b04454 chore: update readme 2025-02-24 22:01:36 +08:00
Johnny 0200ce7681 chore: upgrade golangci-lint 2025-02-24 21:50:39 +08:00
Johnny bbca130d62 chore: bump golang version 2025-02-24 21:47:57 +08:00
XIN_____ a0fabaf012 chore: update cn-zh i18n (#4435) 2025-02-24 10:43:24 +08:00
Michael Baumgarten 9f01b451df feat: match sublist indentation when adding a new item (#4433)
* match sublist indentation

* recursively get last node

* fix linting issues
2025-02-22 20:48:39 +08:00
MHZ 964ae16851 feat: support YouTube video thumbnail in link preview (#4427) 2025-02-22 20:46:58 +08:00
MHZ f17774cb3b feat: prevent attackers from exploiting redirect attack GetLinkMetadata API (#4428)
fix: Prevent attackers from exploiting redirect attack GetLinkMetadata API.
2025-02-21 17:29:17 +08:00
Johnny bc97b66f36 fix: serial updates 2025-02-20 21:38:36 +08:00
johnnyjoy f15fd42ed5 fix: inboxes state 2025-02-20 20:51:08 +08:00
johnnyjoy 7a685d6435 fix: fetch user by username 2025-02-20 20:43:28 +08:00
XIN_____ 1ebe2e9aae chore: update chinese i18n for settings section (#4424) 2025-02-20 20:21:59 +08:00
Johnny ea165db751 chore: update README.md 2025-02-20 17:43:47 +08:00
Johnny c088c5b26a feat: render emoji from shortcut title 2025-02-19 22:13:32 +08:00
Johnny 37eceabc94 chore: fix memo view gap 2025-02-19 22:02:41 +08:00
Johnny cdbaf805b7 chore: pnpm install 2025-02-19 22:00:12 +08:00
Johnny e528203cde chore: remove unused deps 2025-02-19 21:59:45 +08:00
MHZ f8c973c938 fix: prevent previewing internal network web pages. (#4421) 2025-02-19 21:55:24 +08:00
Johnny 2aaaef79f7 chore: fix tests 2025-02-18 22:32:30 +08:00
Johnny 2dc7766fd0 fix: content contains for postgres 2025-02-18 22:28:25 +08:00
taosin 00932d18f5 feat: update i18n zh-hans (#4416) 2025-02-18 10:47:01 +08:00
taosin 6fdfe6b118 chore: update chinese i18n (#4414) 2025-02-17 17:52:18 +08:00
ProjectOrangeJuice 9f25bb2034 feat: trim space on webhook url (#4411) 2025-02-17 10:16:01 +08:00
MHZ 174b8b048a feat: support blur processing for NSFW content with customizable NSFW tags (#4407) 2025-02-16 23:35:31 +08:00
Johnny 47a9b434e6 fix: translate in members section 2025-02-16 22:34:35 +08:00
Johnny 5686fdfb0a chore: handle redirect 2025-02-16 22:17:48 +08:00
Johnny f5394a3e32 chore: update golangci config 2025-02-16 21:42:33 +08:00
Johnny 9299c216e2 chore: move migration to 0.24.0 2025-02-16 21:02:18 +08:00
taosin a7fef80384 chore: update chinese i18n at member setting section (#4405) 2025-02-16 21:00:37 +08:00
Chris Dzombak d25f355392 chore: allow storing resource references >256 chars long in mysql (#4408)
fix: allow storing resource references >256 chars long in mysql
2025-02-16 18:20:51 +08:00
boojack 04d7ba48e5 chore: remove default gzip middleware 2025-02-13 22:00:55 +08:00
Johnny 920b0f64f2 chore: extract auth footer 2025-02-12 22:05:58 +08:00
taosin 3c71ee9d7b chore: update i18n chinese (#4400) 2025-02-12 16:43:44 +08:00
xt 4cd2aa6f32 chore: chinese localization enhancements (#4397)
* Chinese localization enhancements

* Fix for eslint
2025-02-12 10:13:09 +08:00
Johnny 7a57b5c6e7 refactor: user store 2025-02-11 21:29:16 +08:00
Johnny 11b9c240e9 refactor: workspace setting store 2025-02-11 21:23:46 +08:00
Kevin Clark e27f6f0c52 chore: update LICENSE (#4394)
This PR updates the Copyright information for memos.
Related to usememos/memos#4393
2025-02-11 15:45:20 +08:00
Johnny 9027430646 fix: store reactive 2025-02-10 22:20:07 +08:00
CyberSlinger 01a9bb2d49 feat: add zh hans text (#4384)
* feat: test dev push

* feat: add zh Hans text

* feat: restore readme

* feat: update zh hans text

* feat: add tag for properties label

* feat: updarte zh hans translation

* feat: add tab
2025-02-10 10:19:19 +08:00
Simon c9edac9d5a chore: update i18n Ukrainian (#4385)
* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json

* Update uk.json
2025-02-10 10:18:55 +08:00
Martin Hartl ae85dff5e4 chore: add id to RSS feed items (#4383) 2025-02-09 22:24:23 +08:00
Johnny 6abd51fe5a chore: update resource storage type comment 2025-02-09 12:56:30 +08:00
Johnny 49332851d4 chore: go mod tidy 2025-02-09 11:50:16 +08:00
Johnny 0a429a899f chore: remove version update activity 2025-02-09 11:48:53 +08:00
Johnny 983323ceef chore: remove debug code 2025-02-09 11:44:15 +08:00
Johnny 5a2f18da69 refactor(frontend): retire redux 2025-02-09 11:43:55 +08:00
johnnyjoy 13f6fa7b37 refactor: remove default visibility in workspace setting 2025-02-08 11:40:31 +08:00
Steven 9957f8e290 chore: move dsn output to dev mode 2025-02-07 20:59:14 +08:00
Steven 4dfe078f3e chore: tweak memo link is rss 2025-02-07 20:55:38 +08:00
Steven f6ad49754a chore: update url of memo detail page 2025-02-07 20:51:04 +08:00
shungiku 8be0ddfb35 chore: add datepicker to calendar month (#4379)
Co-authored-by: shungiku <79780196+shungikuk@users.noreply.github.com>
2025-02-07 12:53:02 +08:00
Steven e09819da53 chore: add MemoFilters to explore sidebar 2025-02-06 23:35:25 +08:00
Steven 2ed3e34636 refactor: update root layout 2025-02-06 23:20:37 +08:00
johnnyjoy 505fee1abb chore: add noreferrer to external links 2025-02-06 20:19:58 +08:00
johnnyjoy 3a3ffe633d chore: remove latest tag 2025-02-06 19:48:51 +08:00
johnnyjoy 0e303181a9 chore: update action's title 2025-02-06 19:45:05 +08:00
johnnyjoy 849bf66612 fix: remove outdated factor 2025-02-06 19:38:53 +08:00
𝗦𝗵𝗟𝗲𝗿𝗣 48988a8814 fea: improve Turkish Locales (#4375) 2025-02-06 19:11:02 +08:00
Steven dfacb33abe chore: update release action by branch 2025-02-06 09:15:12 +08:00
Steven 84ef3558ab chore: update release action by branch 2025-02-06 09:12:42 +08:00
wzc90 3f33ccd906 fix: update 01__memo_pinned.sql (#4370) 2025-02-06 09:08:31 +08:00
Steven 7996586488 chore: fix migration script for sqlite 2025-02-05 20:56:46 +08:00
johnnyjoy 54a48b58d7 chore: remove random field 2025-02-05 20:48:27 +08:00
johnnyjoy 2a8c4cb750 chore: update styles 2025-02-05 20:30:22 +08:00
johnnyjoy 07336f0392 chore: update condition concat check 2025-02-05 20:07:38 +08:00
johnnyjoy 64dfadb538 chore: update readme 2025-02-05 19:51:09 +08:00
johnnyjoy 732a7d0bbf chore: add fa locale 2025-02-05 19:26:34 +08:00
spidtzz d8b3a69c31 feat: add Farsi(Persian) localazation (#4364)
Add files via upload
2025-02-05 19:19:29 +08:00
shungiku c2210b65ee fix: calendar coloring issue (#4352)
* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* fix: calendar coloring issue

* chore: adjust calendar color for dark theme
2025-02-05 11:13:25 +08:00
RoccoSmit 03267d6d37 feat: search for multiple words (#4362) 2025-02-04 21:04:36 +08:00
johnnyjoy 6c088e09d9 chore: fix import order 2025-02-03 18:35:16 +08:00
johnnyjoy a7ca63434b feat: validate shortcut's filter 2025-02-03 18:34:31 +08:00
johnnyjoy 8f35086da7 chore: update docs link 2025-02-03 18:23:50 +08:00
johnnyjoy ff04fdc459 feat: support more operators in filter 2025-02-03 18:23:09 +08:00
johnnyjoy 03189ee3b2 chore: remove corepack in dockerfile 2025-02-03 17:50:33 +08:00
johnnyjoy f25acfe8e2 chore: fix linter 2025-02-03 17:34:46 +08:00
johnnyjoy e0e735d14d feat: support memo filter for mysql and postgres 2025-02-03 17:14:53 +08:00
hchengting 0f8b7b7fe6 fix: show loader icon while refreshing (#4358) 2025-02-03 15:59:46 +08:00
johnnyjoy 503c892abf chore: buf generate 2025-02-03 15:09:37 +08:00
johnnyjoy b734d429ec chore: fix linter warning 2025-02-03 13:08:13 +08:00
johnnyjoy 364f005ee5 fix: filter 2025-02-03 12:44:01 +08:00
johnnyjoy 2db86f6644 feat: implement shortcut components 2025-02-03 12:26:44 +08:00
johnnyjoy 3a085f3639 chore: fix filter tests 2025-02-03 12:01:34 +08:00
johnnyjoy 8e586d348e chore: fix tag filter 2025-02-03 11:45:26 +08:00
johnnyjoy bf5a29524a chore: remove drop index 2025-02-03 11:45:15 +08:00
johnnyjoy 6682917931 chore: add validate only to create shortcut 2025-02-03 11:45:05 +08:00
johnnyjoy 81e8aed6ab chore: move part of memo filter 2025-02-02 20:28:24 +08:00
johnnyjoy fafd6d81c7 chore: fix linter warning 2025-02-02 18:50:51 +08:00
johnnyjoy be5e24c0eb refactor: renovate list memos endpoint 2025-02-02 18:43:26 +08:00
johnnyjoy 14c72fa7df feat: implement shortcuts 2025-02-02 17:11:52 +08:00
johnnyjoy b9a0c56163 feat: support more factors in filter 2025-02-02 16:12:44 +08:00
johnnyjoy 2a392b8f8d chore: fix import order 2025-02-02 13:52:45 +08:00
johnnyjoy f31800456e chore: fix import order 2025-02-02 13:52:29 +08:00
johnnyjoy 58a867e4da fix: linter warning 2025-02-02 13:50:36 +08:00
johnnyjoy 2d731c5cc5 feat: memo filter for sqlite 2025-02-02 13:35:57 +08:00
johnnyjoy 0af08d9c06 chore: add if exists to postgres 2025-02-02 13:19:56 +08:00
johnnyjoy e6cd761787 chore: remove cgo 2025-02-02 13:07:11 +08:00
dependabot[bot] 66db662e33 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.66.3 to 1.75.2 (#4346)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.66.3 to 1.75.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.66.3...service/s3/v1.75.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:41:26 +08:00
dependabot[bot] 9f99a7de35 chore: bump @types/leaflet from 1.9.15 to 1.9.16 in /web (#4340)
Bumps [@types/leaflet](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/leaflet) from 1.9.15 to 1.9.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/leaflet)

---
updated-dependencies:
- dependency-name: "@types/leaflet"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:43 +08:00
dependabot[bot] ed3923e1ba chore: bump typescript from 5.7.2 to 5.7.3 in /web (#4341)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:30 +08:00
dependabot[bot] 0eed9d5839 chore: bump less from 4.2.1 to 4.2.2 in /web (#4342)
Bumps [less](https://github.com/less/less.js) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/less/less.js/releases)
- [Changelog](https://github.com/less/less.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/less/less.js/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: less
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:21 +08:00
dependabot[bot] a80e407dc5 chore: bump @radix-ui/react-popover from 1.1.4 to 1.1.5 in /web (#4343)
Bumps [@radix-ui/react-popover](https://github.com/radix-ui/primitives) from 1.1.4 to 1.1.5.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-popover"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:13 +08:00
dependabot[bot] 2322f989ea chore: bump actions/stale from 9.0.0 to 9.1.0 (#4344)
Bumps [actions/stale](https://github.com/actions/stale) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:40:04 +08:00
dependabot[bot] 00dd54bae4 chore: bump github.com/lithammer/shortuuid/v4 from 4.0.0 to 4.2.0 (#4345)
Bumps [github.com/lithammer/shortuuid/v4](https://github.com/lithammer/shortuuid) from 4.0.0 to 4.2.0.
- [Release notes](https://github.com/lithammer/shortuuid/releases)
- [Commits](https://github.com/lithammer/shortuuid/compare/v4.0.0...v4.2.0)

---
updated-dependencies:
- dependency-name: github.com/lithammer/shortuuid/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:55 +08:00
dependabot[bot] e034254807 chore: bump github.com/google/cel-go from 0.22.1 to 0.23.2 (#4347)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.22.1 to 0.23.2.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.22.1...v0.23.2)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:42 +08:00
dependabot[bot] 1e9d8f7460 chore: bump golang.org/x/net from 0.33.0 to 0.34.0 (#4348)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.34.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:33 +08:00
dependabot[bot] cda5a5baa4 chore: bump github.com/aws/aws-sdk-go-v2 from 1.32.7 to 1.36.0 (#4349)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.32.7 to 1.36.0.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.32.7...v1.36.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:39:21 +08:00
dependabot[bot] 7a21391446 chore: bump @github/relative-time-element from 4.4.4 to 4.4.5 in /web (#4339)
Bumps [@github/relative-time-element](https://github.com/github/relative-time-element) from 4.4.4 to 4.4.5.
- [Release notes](https://github.com/github/relative-time-element/releases)
- [Commits](https://github.com/github/relative-time-element/compare/v4.4.4...v4.4.5)

---
updated-dependencies:
- dependency-name: "@github/relative-time-element"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-02 09:36:29 +08:00
Xiao Wei 37a81f9d28 fix: migrate sql error (#4338)
* fix: migrate sql error

sqlite not support postgres sql

* Apply suggestions from code review

---------

Co-authored-by: Johnny <yourselfhosted@gmail.com>
2025-02-01 22:11:17 +08:00
johnnyjoy 0b85cb567e chore(frontend): fix clsx 2025-02-01 22:04:29 +08:00
johnnyjoy 57014e392f feat: get user by username 2025-02-01 18:00:22 +08:00
johnnyjoy 45c16f9d52 chore: fix linter 2025-02-01 12:53:48 +08:00
johnnyjoy 0dcd0904e8 refactor: remove resource uid 2025-02-01 12:50:15 +08:00
johnnyjoy 97d12db3d5 refactor: renovate create memo 2025-02-01 11:48:22 +08:00
johnnyjoy 98aa0b73c5 refactor: retire memo uid 2025-02-01 11:28:07 +08:00
johnnyjoy b0119f320a chore: tweak migration scripts 2025-02-01 11:19:36 +08:00
johnnyjoy 5e770dda52 refactor: memo name 2025-02-01 11:17:36 +08:00
RoccoSmit 2f4c5d7bc2 fix: cancel out of no changes save (#4335)
Cancel out of trying to save
2025-02-01 08:30:04 +08:00
johnnyjoy 9bd6d17864 chore: add migration script 2025-01-31 22:00:05 +08:00
johnnyjoy 39d4d4f4f3 chore: update migrate scripts 2025-01-31 21:05:20 +08:00
johnnyjoy d605faeffa refactor: move pinned to memo 2025-01-31 20:58:18 +08:00
johnnyjoy 2058a8ab7b chore: move references to memo property 2025-01-31 14:18:07 +08:00
thehijacker 3fa690964e chore: update Slovenian translation (#4329)
Co-authored-by: Andrej Kralj <andrej.kralj@gmail.com>
2025-01-31 13:39:07 +08:00
Viacheslav Potoropin 7ed3a12a64 fix: internal error on pin/unpin (#4332) 2025-01-31 13:38:43 +08:00
Zero King 5ec3150e0e fix: use correct separator in migration file name (#4327)
Fixes: e913271f15 ("refactor: move tags from property to payload (#4229)")
2025-01-30 12:26:14 +08:00
johnnyjoy 75fd4223bf chore: bump version 2025-01-29 23:41:50 +08:00
changchiakai 9172e47c33 chore: update zh-Hant (#4324)
Update zh-Hant

Co-authored-by: changchiakai <changeric1031@gmail.com>
2025-01-29 09:56:20 +08:00
Philipp Mundhenk 63bbeb9ca3 chore: link to SSO Documentation (#4319)
* Update SSOSection.tsx

linked to SSO (links to Authentik, Authelia, Keycloak), instead of Keycloak only

* Update id.json

* Update uk.json

* Update fr.json

* Update pt-PT.json

* Update vi.json

* Update uk.json

* Update de.json

* Update en.json
2025-01-26 23:03:56 +08:00
Pavel Stržínek 0435a67aa7 feat: czech locale support (#4316) 2025-01-26 23:03:11 +08:00
johnnyjoy 0334a4845f chore: tweak calendar styles 2025-01-21 22:55:57 +08:00
johnnyjoy ef3b7ac6ae chore: update tag icon 2025-01-21 22:55:35 +08:00
johnnyjoy f9b1df5d13 fix: tags container 2025-01-21 22:46:09 +08:00
Comix d9a92b2ef8 feat: support path style of s3 url (#4304)
Signed-off-by: ComixHe <ComixHe1895@outlook.com>
2025-01-21 18:02:21 +08:00
johnnyjoy 702c092289 chore: update auth message 2025-01-20 19:38:50 +08:00
johnnyjoy 409d64b839 chore: update memo comment in activity 2025-01-20 19:34:23 +08:00
johnnyjoy f1308ddd27 refactor: update part of resource identifier 2025-01-19 23:03:22 +08:00
johnnyjoy cda18a37c0 chore: remove docs 2025-01-19 10:50:49 +08:00
johnnyjoy 3c0d011085 chore(dev): update build guides 2025-01-19 10:46:35 +08:00
johnnyjoy f1eacfefb0 chore(dev): update build directory 2025-01-19 10:33:04 +08:00
Steven edc3f1d9d9 chore: retire unused memo view 2025-01-16 09:20:01 +08:00
Steven 147458347b chore: tweak user stats in frontend 2025-01-16 09:12:47 +08:00
johnnyjoy 6904dc16af chore: fix linter 2025-01-15 22:33:18 +08:00
johnnyjoy c76ab87a0a refactor: update list user stats 2025-01-15 19:25:36 +08:00
Steven 8b65d248b1 fix: memo filter 2025-01-14 00:05:33 +08:00
johnnyjoy ee96465be0 feat: list user stats 2025-01-13 23:14:44 +08:00
johnnyjoy cde058c72a chore: tweak theme code 2025-01-13 19:46:06 +08:00
Query&mut NinjaStyle, &Ryder 94517490f5 fix: mermaid diagrams in dark mode (#4289)
* fix #4257 fixed ui for mermaid diagrams in dark mode

* fixed linting issues

* added dynamic color theme for mermaid diagrams

* now mermaid block uses theme according to the system as well when 'follow system' is selected

* refactored code for mermaid theme logic

* refactored mermaid code to use const instead of function call

---------

Co-authored-by: root <root@DESKTOP-G3MCU14>
2025-01-13 19:44:53 +08:00
johnnyjoy d050a6fd46 chore: update user stats 2025-01-11 20:12:02 +08:00
johnnyjoy 34c26a394a feat: implement user stats endpoint 2025-01-11 16:59:22 +08:00
Steven 5ff8ab9a61 chore: polish creator definition 2025-01-10 23:39:50 +08:00
Steven 8b7e9f5443 chore: remove unused user id 2025-01-10 23:35:00 +08:00
RoccoSmit 3081015692 feat: date picker navigation (#4286)
Added month and year dropdowns
2025-01-10 22:46:08 +08:00
johnnyjoy 2cd524e4fa chore: fix buf format 2025-01-10 22:29:57 +08:00
johnnyjoy a1be73cce3 chore: buf format 2025-01-10 22:26:19 +08:00
johnnyjoy c1498a1844 chore: retire webhook state 2025-01-10 22:24:12 +08:00
johnnyjoy 2a861ea430 refactor: tweak resource state in api 2025-01-10 22:20:23 +08:00
johnnyjoy 1caaef1c5b chore: fix memo compact mode 2025-01-10 21:47:00 +08:00
Query&mut NinjaStyle, &Ryder 972ebbae2f fix: compact mode storage (#4279)
fix #4274 now when checkbox is toggled the memo remembers the compact state

Co-authored-by: root <root@DESKTOP-G3MCU14>
2025-01-10 20:43:46 +08:00
johnnyjoy ac7121c21a chore: update archived page 2025-01-10 20:24:05 +08:00
johnnyjoy 5d40f38956 chore: fix name comments 2025-01-09 21:35:02 +08:00
Steven 840b16f041 chore: tweak back to top button 2025-01-08 22:59:08 +08:00
Steven 012ca1d780 fix: tag stats 2025-01-08 22:35:34 +08:00
johnnyjoy d9d6f73330 chore: fix memo converter 2025-01-08 20:57:34 +08:00
johnnyjoy 65da94521d chore: buf generate 2025-01-08 20:29:20 +08:00
Pierre Quillery cdadf133d0 chore: adding missing translations (#4273)
* Added missing translations strings (filters, about page, ...)

* Forgot one translation string.

* Fixed PR issues and added Access Token related missing translation strings.

* Fixed eslint issues.

* Fixed eslint issues #2.

* Fixed access token dialog translations, added missing webhook dialog translations.
2025-01-08 10:24:41 +08:00
Chris Curry 7b909fb772 feat: scroll to top (#4244) 2025-01-04 23:44:37 +08:00
Chris Curry d81174ad7c feat: optimize filters sync (#4260)
* refactor: add bi-directional filters sync between filterStore and searchParams

* fix: tag redirection from memos detail page, https://github.com/usememos/memos/issues/4232
2025-01-04 23:42:49 +08:00
tungerno e3d1967db8 chore: add missing german translations (#4268) 2025-01-04 23:42:29 +08:00
Pierre Quillery 50d09bb91e chore: added missing French translations (#4270)
Added missing French translations.
2025-01-04 23:42:09 +08:00
dependabot[bot] 828461d430 chore: bump golang.org/x/net from 0.30.0 to 0.33.0 (#4251)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.30.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.30.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 10:23:29 +08:00
Chris Curry e3b378b03b feat: persist memo filters with url query (#4239)
* feat: persist memo filters with url query

- Implemented synchronization of memo filters with URL search parameters.
- Enhanced memo store to manage current request state for fetching memos, allowing for request cancellation, avoiding the race conditions.

* refactor: update import
2025-01-02 10:23:15 +08:00
dependabot[bot] 0e1ac30462 chore: bump react-router-dom from 6.28.1 to 7.1.1 in /web (#4246)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.28.1 to 7.1.1.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.1.1/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:25 +08:00
dependabot[bot] 94c47cc520 chore: bump i18next from 23.16.8 to 24.2.0 in /web (#4247)
Bumps [i18next](https://github.com/i18next/i18next) from 23.16.8 to 24.2.0.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.16.8...v24.2.0)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:15 +08:00
dependabot[bot] 93f01f02e1 chore: bump @types/node from 22.10.2 to 22.10.3 in /web (#4248)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.10.2 to 22.10.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:45:05 +08:00
dependabot[bot] fd257ba900 chore: bump @mui/joy from 5.0.0-beta.48 to 5.0.0-beta.51 in /web (#4249)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.48 to 5.0.0-beta.51.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:55 +08:00
dependabot[bot] 00df48e594 chore: bump google.golang.org/grpc from 1.67.1 to 1.69.2 (#4250)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.69.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.69.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:44 +08:00
dependabot[bot] 00c7ea229c chore: bump github.com/aws/aws-sdk-go-v2/config from 1.28.2 to 1.28.7 (#4252)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.28.2 to 1.28.7.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.2...config/v1.28.7)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:27 +08:00
dependabot[bot] 3b57b03e57 chore: bump golang.org/x/crypto from 0.29.0 to 0.31.0 (#4253)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:18 +08:00
dependabot[bot] 2b681bf594 chore: bump golang.org/x/mod from 0.21.0 to 0.22.0 (#4254)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/mod/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-02 09:44:08 +08:00
Steven aff6b8707d chore: upgrade frontend dependencies 2025-01-01 07:59:56 +08:00
Chris Curry bc0bac94ed refactor: enhance hyperlink handling in markdown shortcuts (#4238) 2024-12-30 17:46:24 +08:00
Hadley Rich 82b5c8ab07 feat: add sh entrypoint to allow MEMOS_DSN_FILE to load variable from secret (#4236)
Add sh entrypoint to allow MEMOS_DSN_FILE to load variable from secret
2024-12-30 17:46:02 +08:00
johnnyjoy 7817ad07f7 chore: fix linter 2024-12-30 09:18:11 +08:00
johnnyjoy 3220adbff9 refactor: split memo service 2024-12-26 20:13:05 +08:00
johnnyjoy a78bfffb17 chore: add output only flag 2024-12-26 20:06:42 +08:00
johnnyjoy 541e07af8c chroe: rebuild memo references 2024-12-26 20:04:36 +08:00
johnnyjoy 3b0be442de chore: update memo payload runner schedule 2024-12-26 20:01:15 +08:00
johnnyjoy 41d9c9d76e fix: order list starts 2024-12-25 22:43:26 +08:00
Johnny e913271f15 refactor: move tags from property to payload (#4229)
* refactor: move tags from property to payload

* chore: fix tests

* chore: drop memo tags

* chore: update

---------

Co-authored-by: Steven <stevenlgtm@gmail.com>
2024-12-24 15:23:15 +00:00
zjy4fun f15346e615 fix: optimize memoMap generation logic to ensure memoMap count matche… (#4214)
fix: optimize memoMap generation logic to ensure memoMap count matches memos
2024-12-20 13:22:48 +08:00
zjy4fun 7a77b4ba38 chore: fix css location compatibility issues on Safari (#4215)
chore: fix location compatibility issues on Safari

closes https://github.com/usememos/memos/issues/4190
2024-12-20 13:21:59 +08:00
RoccoSmit ce6ad4035d fix: limit the size of the resource list viewer (#4210)
Limit the size of the file upload box
2024-12-19 10:32:05 +08:00
Lincoln Nogueira 1c255d4e1f fix: panic on arm v5-v6-v7 builds (#4204)
- upgrade modernc.org/libc to v1.34.2

libc version on go.mod must match upstream's sqlite go.mod file to prevent similar issues.

https://pkg.go.dev/modernc.org/sqlite#hdr-Fragile_modernc_org_libc_dependency

```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGBUS: bus error code=0x2 addr=0x0 pc=0xdd8568]
```
2024-12-16 14:31:58 +08:00
Nikolay ea394d89b2 fix: add server name change in mobile header (#4195)
* [fix] add server name change in  mobile header

* Update web/src/components/MobileHeader.tsx

* Update web/src/components/MobileHeader.tsx

* Apply suggestions from code review

---------

Co-authored-by: Николай Витальевич Никоноров <nnv@bitt.moe>
Co-authored-by: Johnny <yourselfhosted@gmail.com>
2024-12-13 13:23:16 +08:00
johnnyjoy cb569c99fd chore: remove useCallback in fetching memo list 2024-12-07 12:26:21 +08:00
johnnyjoy 5a83f0c4fa chore: update frontend dependencies 2024-12-07 12:22:54 +08:00
johnnyjoy f1d6a6766e chore: revert bump react version 2024-12-07 12:19:55 +08:00
johnnyjoy 0a5111e4b0 chore: update i18n types definition 2024-12-07 12:16:38 +08:00
Johnny 67f8811f3f chore: tweak bug report template 2024-12-07 11:48:02 +08:00
Steven a97154e72d chore: bump react version 2024-12-06 22:16:18 +08:00
dependabot[bot] dd15012661 chore: bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#4164)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:44 +08:00
dependabot[bot] 6e88b4203b chore: bump github.com/google/cel-go from 0.22.0 to 0.22.1 (#4165)
Bumps [github.com/google/cel-go](https://github.com/google/cel-go) from 0.22.0 to 0.22.1.
- [Release notes](https://github.com/google/cel-go/releases)
- [Commits](https://github.com/google/cel-go/compare/v0.22.0...v0.22.1)

---
updated-dependencies:
- dependency-name: github.com/google/cel-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:34 +08:00
dependabot[bot] 6cdc90bc97 chore: bump google.golang.org/protobuf from 1.35.1 to 1.35.2 (#4166)
Bumps google.golang.org/protobuf from 1.35.1 to 1.35.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:24 +08:00
dependabot[bot] d06e67f57c chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.43 to 1.17.46 (#4167)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.43 to 1.17.46.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.43...credentials/v1.17.46)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 09:00:10 +08:00
dependabot[bot] 4e99de2692 chore: bump @bufbuild/buf from 1.46.0 to 1.47.2 in /web (#4169)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.46.0 to 1.47.2.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.46.0...v1.47.2)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:59 +08:00
dependabot[bot] edb8db9914 chore: bump @reduxjs/toolkit from 2.3.0 to 2.4.0 in /web (#4170)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:48 +08:00
dependabot[bot] 1e28f7abb5 chore: bump tailwind-merge from 2.5.4 to 2.5.5 in /web (#4171)
Bumps [tailwind-merge](https://github.com/dcastil/tailwind-merge) from 2.5.4 to 2.5.5.
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/compare/v2.5.4...v2.5.5)

---
updated-dependencies:
- dependency-name: tailwind-merge
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:38 +08:00
dependabot[bot] 56c9e94ac4 chore: bump class-variance-authority from 0.7.0 to 0.7.1 in /web (#4172)
Bumps [class-variance-authority](https://github.com/joe-bell/cva) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/joe-bell/cva/releases)
- [Commits](https://github.com/joe-bell/cva/compare/v0.7.0...v0.7.1)

---
updated-dependencies:
- dependency-name: class-variance-authority
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:27 +08:00
dependabot[bot] 790004463b chore: bump less from 4.2.0 to 4.2.1 in /web (#4173)
Bumps [less](https://github.com/less/less.js) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/less/less.js/releases)
- [Changelog](https://github.com/less/less.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/less/less.js/commits)

---
updated-dependencies:
- dependency-name: less
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:59:16 +08:00
dependabot[bot] 77e4d6f6f1 chore: bump golang.org/x/crypto from 0.28.0 to 0.29.0 (#4168)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 08:49:13 +08:00
Cheng 2aa3795e50 fix: search conditions affected by pull-to-refresh (#4159) 2024-11-29 22:13:41 +08:00
Query&mut NinjaStyle, &Ryder 009f4956ac fix: check IdP for disallow password auth
* fix #4144 now when there is no sso then the Disallow password auth is disabled

* fixed the import issue

* attempt fixing linting issues

---------

Co-authored-by: pransh62390 <63577123+pransh62390@users.noreply.github.com>
2024-11-29 12:23:17 +08:00
KidLoveToPlay 73d13cb97b chore: style fix to #4151 (#4153)
* chore: apply styles to the correct month

* chore: style fix
2024-11-28 10:23:28 +08:00
KidLoveToPlay 97ef5a8871 chore: apply styles to the correct month (#4151) 2024-11-27 14:00:50 +08:00
Madhur Jodhwani a51e363c7c chore: fix truncation of webhook url to avoid disappearance of Trash Icon (#4145)
* Fixed truncation of webhook url to avoid disappearance of Trash Icon

* fixing webhook truncation issue #4078

* Removing overflow-hidden

* resolving pipeline issues

* supporting on hover url display

---------

Co-authored-by: Madhur <madhur.jodhwani@accelya.com>
2024-11-25 14:19:04 +08:00
RoccoSmit 54ee2bf3ab feat: show less when memo expanded (#4143)
* Added show less action and language files

* Renaming type as suggested in pr review
2024-11-24 22:24:58 +08:00
johnnyjoy 2a1c0bba6c chore: remove unused reaction.proto 2024-11-21 23:08:03 +08:00
JP Hastings-Edrei fcc4abf5b8 feat: remove RSS titles (#4140)
This removes the content of the <title> element in the RSS feeds that Memo produces.

Why remove? Every RSS client I can find shows the <title> next to the <description> when viewing an item. This creates a duplicate (but often trimmed, so less useful) version of <description> right above the actual text the user wants to read (often in a much larger font). It similarly makes lists of items in some clients extremely tall, as 128 characters is a lot of hard-to-read text — especially when Memos renders links as their URL in titles.

Why an empty tag? The RSS 1.0 and 2.0 specs require that a <title> element is present.

Examples from elsewhere:
- micro.blog uses an empty <title /> element: https://www.manton.org/feed.xml
- Bluesky omits the <title> element: https://bsky.app/profile/did%3Aplc%3Aqvzn322kmcvd7xtnips5xaun/rss
- Mastodon omits the <title> element: https://mastodon.social/@scalzi.rss
2024-11-20 22:31:32 +08:00
Steven 51c80c37d1 revert: tweak reaction_type column type for mysql 2024-11-20 20:37:35 +08:00
Steven 9f2c1b2556 chore: tweak reaction_type column type for mysql 2024-11-20 20:35:03 +08:00
Steven 104948ae40 chore: set pull to refresh with screen size 2024-11-20 20:28:49 +08:00
Steven 7b70c203cc chore: buf generate 2024-11-20 20:22:21 +08:00
nlfox 3cbccde67e feat: add pull to refresh for PagedMemoList (#4128) 2024-11-19 23:34:47 +08:00
johnnyjoy 1424036ccd chore: use for...of 2024-11-17 22:04:49 +08:00
Andy An f6af564d4e feat: enhancement on UI/UX on user statistic view part. (#4122)
Enhancement on UI/UX on user statistic view part.
2024-11-17 09:47:41 +08:00
lcdgit f00751a6e0 feat: allow to remove done items (#4126)
* add remove done items

* i18n en add

* bug fix

* add i18n

* Modify the description

* Modify the description

* Modify the description

* remove remove_done_check_items setting

* fix the static checks

* fix the static checks

---------

Co-authored-by: mozhu <lcl_em@163.com>
2024-11-17 09:33:39 +08:00
johnnyjoy 80785de900 chore: remove unused script 2024-11-14 22:12:00 +08:00
Steven 378b6a51c1 chore: tweak default reactions 2024-11-13 08:33:12 +08:00
Steven f007185b8f chore: tweak form styles 2024-11-12 23:23:14 +08:00
RoccoSmit 142e97ab5a feat: navigate image view with keyboard keys (#4116)
* Navigate images with keyboard left and right keys

* Fix linting

* Adding missing "

* Added change to incorrect branch
2024-11-11 08:16:09 +08:00
RoccoSmit bcd8856732 fix: added missing " (#4119)
Added missing "
2024-11-11 08:14:17 +08:00
johnnyjoy 45d4d391d8 fix: air script in windows 2024-11-07 23:34:39 +08:00
johnnyjoy 2f8d347310 Merge branch 'main' of https://github.com/usememos/memos 2024-11-07 23:32:49 +08:00
johnnyjoy b4f9c09d85 chore: upgrade backend dependencies 2024-11-07 23:32:44 +08:00
Steven 5601daef40 chore: add semantic action 2024-11-06 21:15:53 +08:00
Steven ad50aec2db chore: update activity calendar 2024-11-06 21:14:36 +08:00
RoccoSmit 3b25a6bbec fix: handle missing reaction (#4094)
* migration version

* Updated test to match with current version set in version.go file

* updated logic to check if migration should run for fresh install

* Update test to test for version number set in version.go

* fixed test

* Revert "fixed test"

This reverts commit 4004d0e92b.

* Revert "Update test to test for version number set in version.go"

This reverts commit d304add5d6.

* Revert "updated logic to check if migration should run for fresh install"

This reverts commit b44dca2194.

* Revert "Updated test to match with current version set in version.go file"

This reverts commit 3ad0d889b6.

* Revert "migration version"

This reverts commit b13cfc346a.

* Added default reaction if no reation found

* Fixed static check issue

* Use emoji
2024-11-06 21:11:26 +08:00
johnnyjoy 3786fb8db2 chore(dev): add code inspector plugin 2024-11-06 19:28:18 +08:00
Steven 67c1a46346 chore: remove html renderer sanitizes 2024-11-05 22:44:37 +08:00
Steven 57c00734e2 fix: frontend build 2024-11-05 21:15:13 +08:00
Ngô Quốc Đạt e25792be9c chore: update vi translations (#4099) 2024-11-05 15:29:43 +08:00
Steven f5a0827a3f chore: update explore translate of zh-hans 2024-11-04 21:38:34 +08:00
Steven 04c6e262c3 chore: align colors 2024-11-04 21:30:50 +08:00
Simon f310207b9a chore: update i18n Ukrainian (#4096)
* Update uk.json

* Update uk.json
2024-11-04 20:04:20 +08:00
Steven 7b79c49414 chore: remove version tests 2024-11-03 22:55:09 +08:00
Steven b547720aa8 chore: add id to i18n locales 2024-11-03 22:48:39 +08:00
kiraware 3542a79420 feat: add Bahasa Indonesia (id) translation (#4092) 2024-11-03 22:45:49 +08:00
johnnyjoy 227cc26cb9 chore: align table styles for access token section 2024-11-03 20:28:42 +08:00
Steven f59daf839b chore: fix action 2024-11-02 20:00:00 +08:00
Steven ae957439ec chore: update build action 2024-11-02 19:56:07 +08:00
Steven 4b28dfddb6 fix: visibility selector overflow 2024-11-02 13:39:08 +08:00
dependabot[bot] 648db7e82a chore: bump uuid from 10.0.0 to 11.0.2 in /web (#4086)
Bumps [uuid](https://github.com/uuidjs/uuid) from 10.0.0 to 11.0.2.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v10.0.0...v11.0.2)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 11:58:31 +08:00
dependabot[bot] bd4e4b632a chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.25 to 1.17.35 (#4084)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.25 to 1.17.35.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.25...credentials/v1.17.35)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 11:58:17 +08:00
dependabot[bot] a449988a7e chore: bump golang.org/x/crypto from 0.27.0 to 0.28.0 (#4085)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/crypto/compare/v0.27.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:40 +08:00
dependabot[bot] 6be36d268a chore: bump @types/node from 22.8.0 to 22.8.6 in /web (#4087)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.0 to 22.8.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:25 +08:00
dependabot[bot] c1a13be778 chore: bump golang.org/x/net from 0.29.0 to 0.30.0 (#4082)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:39:08 +08:00
dependabot[bot] d2c4a9e7b6 chore: bump github.com/aws/aws-sdk-go-v2 from 1.31.0 to 1.32.3 (#4083)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.31.0 to 1.32.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.31.0...v1.32.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:58 +08:00
dependabot[bot] bb9b6be19e chore: bump zustand from 4.5.5 to 5.0.1 in /web (#4090)
Bumps [zustand](https://github.com/pmndrs/zustand) from 4.5.5 to 5.0.1.
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v4.5.5...v5.0.1)

---
updated-dependencies:
- dependency-name: zustand
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:39 +08:00
dependabot[bot] 183a22a928 chore: bump @bufbuild/buf from 1.45.0 to 1.46.0 in /web (#4088)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.45.0 to 1.46.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.45.0...v1.46.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:38:04 +08:00
dependabot[bot] aea814de83 chore: bump @bufbuild/protobuf from 2.2.0 to 2.2.2 in /web (#4089)
Bumps [@bufbuild/protobuf](https://github.com/bufbuild/protobuf-es/tree/HEAD/packages/protobuf) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/bufbuild/protobuf-es/releases)
- [Commits](https://github.com/bufbuild/protobuf-es/commits/v2.2.2/packages/protobuf)

---
updated-dependencies:
- dependency-name: "@bufbuild/protobuf"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 10:36:27 +08:00
Daniel Pinto f44583e87d chore: allow some hardcoded strings to be translated (#4076)
Allow some hardcoded strings to be translated

Also add pt-PT translation for them
2024-11-02 10:36:11 +08:00
johnnyjoy 9a4fc2e015 chore: buf generate 2024-10-30 21:52:27 +08:00
Steven 67e474d4dd fix: linter warning 2024-10-30 20:19:08 +08:00
Steven c12425329b chore: fix action buttons 2024-10-29 00:18:02 +08:00
Steven db2b34a850 chore: update input source 2024-10-28 22:04:52 +08:00
Daniel Pinto 12bcf65f7d locale: Add pt-PT translations (#4064)
* locale: Add pt-PT translations

* fix str
2024-10-28 09:14:00 +08:00
Steven f373d8e88c chore: update checkbox source 2024-10-27 10:19:06 +08:00
Steven 963706aebd refactor: update button source 2024-10-26 21:36:05 +08:00
Steven 8635aed138 chore: update dependencies 2024-10-25 21:55:00 +08:00
new-aspect aa9649adf0 fix: automatic indentation follows previous lines in lists (#4048) (#4050)
* fix: automatic indentation follows previous lines in lists (#4048)

* fix: automatic indentation follows previous lines in lists (#4048)
change the position of this logic and recommit it
2024-10-25 19:16:59 +08:00
RoccoSmit 2851f11302 fix: use UTC date for calendar filter (#4046) 2024-10-23 22:52:20 +08:00
johnnyjoy 7e48d13834 fix: workspace setting state 2024-10-23 13:46:07 +08:00
Steven 4fcc682a15 chore: add beta badge to relation graph 2024-10-21 20:23:34 +08:00
Steven f9fec56560 chore: fix date picker position 2024-10-20 17:08:01 +08:00
johnnyjoy 2ebf3f2615 chore: fix math styles 2024-10-19 21:40:24 +08:00
johnnyjoy cf1be81de2 feat: use date-picker instead of raw datetime input 2024-10-19 21:30:02 +08:00
johnnyjoy 199d5680e6 chore: update inbox messages style 2024-10-19 21:01:02 +08:00
johnnyjoy 435bd5c44f fix: update relation graph checks 2024-10-19 20:53:53 +08:00
johnnyjoy 04d6329d0f feat: use hash router to sub-setting pages 2024-10-19 20:46:57 +08:00
johnnyjoy 085995ec3d chore: update setting title 2024-10-19 20:32:55 +08:00
johnnyjoy c3cb3770cc chore: tweak function names 2024-10-19 16:13:33 +08:00
johnnyjoy c2e820400e chore: regenerate api docs 2024-10-19 16:13:27 +08:00
d0zingcat 67dc9a3f0a chore: allow quick unpin (#4031)
Signed-off-by: d0zingcat <leewtang@gmail.com>
2024-10-19 16:05:14 +08:00
Matteo Vollero 19098940f7 chore: check currentUser and redirect to index if logged (#4021)
* If to check currentUser and redirect to index if logged

* Moved check into useEffect
2024-10-19 16:04:34 +08:00
d0zingcat e5cb2037e4 feat: allow to disable markdown shortcuts (#4025)
* add settting to disable markdown keymap

Signed-off-by: d0zingcat <leewtang@gmail.com>

* rename disable markdown shortcuts

Signed-off-by: d0zingcat <leewtang@gmail.com>

* fix lint

Signed-off-by: d0zingcat <leewtang@gmail.com>

---------

Signed-off-by: d0zingcat <leewtang@gmail.com>
2024-10-16 23:27:54 +08:00
Steven 009534f1cf chore: fix linter warning 2024-10-16 23:11:34 +08:00
Steven 68c2bd3837 chore: update memo relations 2024-10-16 23:09:20 +08:00
Steven 82da20e1c3 feat: implement graph of relations 2024-10-15 23:31:44 +08:00
Steven 952428c15d chore: update default max height 2024-10-15 20:38:17 +08:00
Steven cfe1765067 chore: tweak user statistics view 2024-10-15 20:30:24 +08:00
Steven c4b52c68b5 fix: max height of memo content compact mode 2024-10-15 20:07:55 +08:00
Steven 317cf06579 chore: tweak demo data 2024-10-14 23:35:19 +08:00
Steven 14712b42fa chore: add pagination to list inboxes 2024-10-14 23:32:39 +08:00
Steven b4d72e3349 fix: memo visibilities with filter 2024-10-14 21:31:44 +08:00
Steven 60a0ead0fa chore: add ka-GE locale 2024-10-14 20:31:45 +08:00
Aleksandre 69e93c1ab4 feat: support Georgian Language (#4016)
Create ge.json

Georgian language
2024-10-14 09:46:48 +08:00
Steven b2f60758bc chore: update workspace setting in demo mode 2024-10-12 09:21:00 +08:00
Steven 74498a726e chore: update package 2024-10-11 21:35:25 +08:00
Steven cab981c393 chore: fix linter errors 2024-10-11 21:27:08 +08:00
Steven 3370ecd4fc chore: ignore lint for tests 2024-10-11 21:22:04 +08:00
Steven 0a871b8960 chore: fix tests 2024-10-11 21:13:36 +08:00
RoccoSmit 35cf975e76 fix: apply system theme dynamically (#4010)
Remove appearance comparison
2024-10-11 21:05:52 +08:00
Steven 43d13a3edc chore: tweak linter 2024-10-11 21:05:07 +08:00
Steven f467f1d9f6 chore: update cron package 2024-10-11 19:59:14 +08:00
Steven 0b6f24a21a chore: update task complete 2024-10-10 23:22:18 +08:00
Steven d066d46f6e chore: tweak schema version 2024-10-10 22:30:46 +08:00
Steven d54c8065b5 chore: update demo data 2024-10-10 22:04:41 +08:00
Steven 2acad978d1 chore(frontend): add reactions setting 2024-10-10 22:04:35 +08:00
Steven e527b6a878 feat: move reaction type to setting 2024-10-10 21:06:32 +08:00
wjsoj 1f9d657065 feat: support set global Default memo visibility (#3989)
* feat: support set global Default memo visibility

* feat: Move to WorkspaceMemoRelatedSetting

* fix: goimports check failure

* chore: change item name to default_visibility

* fix: goimports check failure
2024-10-08 22:45:18 +08:00
Steven dc15e8f30f chore: implement memo metadata store 2024-10-08 22:22:45 +08:00
johnnyjoy 831c254d64 fix: update user fields 2024-10-08 19:52:49 +08:00
Roman 310f147911 feat: allow single letter user id (#3991)
* Allow single letter user id.

They do work - I use one and login using Authelia, but then I am not able to update the profile to update avatar or add comment because "Invalid username: r" errors

* Add test for the util with uid matcher

* Move the test to separate directory

* Use goimports on the test file

* Rename the test for a mroe matching name, add failing test

* Update the regexp so that two letter work

---------

Co-authored-by: Roman Kamyk <roman@kamyk.me>
2024-10-08 13:47:24 +08:00
Steven 0b2f08ad15 fix: memo view 2024-10-07 01:57:37 +08:00
Steven d11e7a3a9a chore: remove duplicated requests 2024-10-07 01:40:15 +08:00
Steven c401a07933 chore: update dependencies 2024-10-02 22:22:21 +08:00
RoccoSmit f0d43c9577 feat: add tag count to tree view (#3970)
* Add tag count to tree view

* Only display tag amounts > 1

* Updated tag amount var name to be more descriptive

* - Moved display logic to html in return
- Updated var names to closer match var passed in by TagSection component
2024-10-02 18:31:50 +08:00
dependabot[bot] 4ab06f5f11 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.22 to 1.17.25 (#3978)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.22 to 1.17.25.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.22...credentials/v1.17.25)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:42 +08:00
dependabot[bot] dab0f1907d chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.36 to 1.27.39 (#3976)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.36 to 1.27.39.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.36...config/v1.27.39)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:33 +08:00
dependabot[bot] e7949d0748 chore: bump vite from 5.4.7 to 5.4.8 in /web (#3981)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.7 to 5.4.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.8/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:37:16 +08:00
Xavier Hocquet 32123e0c21 feat: add month toggle on hover (#3972)
* Add month toggle on hover

* Lint
2024-10-02 11:37:05 +08:00
dependabot[bot] 4c0c7431c8 chore: bump google.golang.org/grpc from 1.67.0 to 1.67.1 (#3977)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.0 to 1.67.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.0...v1.67.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:36:12 +08:00
dependabot[bot] 25367bc000 chore: bump nice-grpc-web from 3.3.4 to 3.3.5 in /web (#3979)
Bumps [nice-grpc-web](https://github.com/deeplay-io/nice-grpc) from 3.3.4 to 3.3.5.
- [Release notes](https://github.com/deeplay-io/nice-grpc/releases)
- [Commits](https://github.com/deeplay-io/nice-grpc/compare/nice-grpc-web@3.3.4...nice-grpc-web@3.3.5)

---
updated-dependencies:
- dependency-name: nice-grpc-web
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:36:00 +08:00
dependabot[bot] 6cd86c0de1 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.34 to 1.17.37 (#3975)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.34 to 1.17.37.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.34...credentials/v1.17.37)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:35:40 +08:00
dependabot[bot] 508146b052 chore: bump mermaid from 10.9.1 to 11.2.1 in /web (#3980)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 11.2.1.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...mermaid@11.2.1)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 11:35:28 +08:00
dependabot[bot] 143167386e chore: bump dompurify from 3.1.6 to 3.1.7 in /web (#3982)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.6...3.1.7)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 07:43:34 +08:00
dependabot[bot] 938cfb4a69 chore: bump @types/node from 22.5.5 to 22.7.4 in /web (#3983)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.5 to 22.7.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 07:43:26 +08:00
dependabot[bot] 6965f0b89d chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.63.0 to 1.63.3 (#3974)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.63.0 to 1.63.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.63.0...service/s3/v1.63.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 05:14:26 +08:00
ElTopo 0ba36ed7e0 chore: updated zh-Hans.json from current version of en.json (#3966) 2024-09-30 10:48:36 +08:00
Steven 771a977c9f chore: tweak words 2024-09-29 22:49:29 +08:00
Steven 69ad5178b3 chore: update MaxCallRecvMsgSize 2024-09-29 22:00:15 +08:00
Steven 2b86069f3b chore: update MaxRecvMsgSize 2024-09-29 21:58:06 +08:00
johnnyjoy d5d37c1d59 chore: bump gomark version 2024-09-28 21:55:58 +08:00
Steven cf4e660f41 chore: add memo location setting 2024-09-26 22:11:37 +08:00
Steven 95a50b6596 chore: tweak leaflet map 2024-09-26 22:04:05 +08:00
Steven 9c41c8d5c9 chore: fix marker icon 2024-09-26 09:20:33 +08:00
Steven 2837816ff7 chore: fix component state 2024-09-26 00:27:39 +08:00
Steven b144faf43a feat: add location selector 2024-09-26 00:03:17 +08:00
Steven 63989ab365 feat: add location to memo payload 2024-09-25 21:48:54 +08:00
Steven 92c41458a9 chore: fix release action 2024-09-25 20:03:27 +08:00
Steven a55afbd3ed chore: tweak build actions 2024-09-25 19:57:14 +08:00
boojack 9c4d25cc4d chore: update README.md 2024-09-25 19:47:12 +08:00
Steven 8b444be6ca chore: update tag search 2024-09-23 21:41:23 +08:00
Steven 171a89564e chore: tweak gen apidocs 2024-09-23 08:43:16 +08:00
RoccoSmit 6cbe957db2 fix: show future relative dates (#3946)
Show future relative dates
2024-09-22 22:24:46 +08:00
auphone 0711ac4ecb feat: allow mobile user zooming in image preview (#3880)
* Set viewport scalable in image preview dialog for mobile zooming and reset it on destroy

* Format with prettier

* move setViewportScalable() into useEffect

* use const instead of function
2024-09-22 21:48:01 +08:00
Steven ea881338a9 chore: add gradient block to compact mode 2024-09-22 21:15:46 +08:00
johnnyjoy 7817947f66 fix: clean duplicated requests 2024-09-22 19:51:55 +08:00
johnnyjoy 1f7a90cec4 chore: add spinner to paged memo list 2024-09-22 19:41:27 +08:00
johnnyjoy 339c38750f refactor: paged memo list container 2024-09-22 19:30:39 +08:00
johnnyjoy 41976cb894 feat: update memo endpoints 2024-09-22 15:43:46 +08:00
johnnyjoy c28516b35f chore: buf generate 2024-09-22 13:57:47 +08:00
Steven ca213437e9 feat: implement nesting lists 2024-09-21 20:02:47 +08:00
johnnyjoy 7a4d54bb3c chore: update error messages 2024-09-21 18:23:30 +08:00
johnnyjoy f102aeb9b9 chore: tweak golangci version 2024-09-21 18:10:05 +08:00
johnnyjoy a6de047b64 chore: fix actions 2024-09-21 17:54:51 +08:00
johnnyjoy 9130d981fa chore: fix actions 2024-09-21 17:37:57 +08:00
johnnyjoy b915eaa620 chore: bump dependencies 2024-09-21 17:36:53 +08:00
Johnny a81d7b3260 chore: revert "perf: reduce image size by 21.3MB" (#3942)
Revert "perf: reduce image size by 21.3MB (#3849)"

This reverts commit 0156c7e11f.
2024-09-21 17:33:01 +08:00
johnnyjoy 8cdc956e59 chore: update ts proto 2024-09-21 17:25:57 +08:00
John Regan 46830e31ec buf: specify version of stephenh-ts-proto plugin (#3941) 2024-09-21 07:36:37 +08:00
Sriniwas 2db67118fc fix: case insensetive memo search for postgres (#3938)
fix:case insensetive memo search for postgres #3892
2024-09-19 23:14:51 +08:00
thehijacker f6ebfdf7f9 feat: update Slovenian translation (#3935)
Updated Slovenian translation

Co-authored-by: Andrej Kralj <andrej.kralj@t-2.com>
2024-09-18 16:52:43 +08:00
Steven ec2b59bff5 chore: bump gomark 2024-09-17 20:41:13 +08:00
Steven d663313ca2 chore: fix frontend linter 2024-09-17 19:09:05 +08:00
Steven fbe0251eed feat: impl list renderer 2024-09-17 19:03:10 +08:00
johnnyjoy 759f7c6171 chore: fix workspace setting tests 2024-09-14 08:27:37 +08:00
johnnyjoy 1da0752922 chore: add schema version to workspace setting 2024-09-14 08:23:39 +08:00
Zisu Zhang b787d1c7b6 feat: support disable change username and nickname (#3911)
* feat: support disable change username and nickname

* chore: update UX
2024-09-12 13:45:04 +08:00
ti777777 6f3d5762ca fix: iframe rendering (#3916)
* fix iframe rendering

* fix eslint check
2024-09-12 08:54:33 +08:00
RoccoSmit 42bc769d5d fix: load server name and icon from settings (#3908) 2024-09-10 23:02:48 +08:00
Steven 4790e84b98 chore: use ratio instead of max width 2024-09-09 21:43:47 +08:00
Steven 76a9a343a5 chore: fix linter 2024-09-09 20:36:35 +08:00
RoccoSmit f695e93f20 fix: update first day logic for months starting on Sunday (#3896)
* Update calendar logic to accomodate for months starting on Sunday

* Apply suggestions from code review

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-09-09 09:19:12 +08:00
RoccoSmit 05d5fb4b04 chore: use translations for calendar days (#3895)
Use translations for calendar days
2024-09-08 20:24:59 +08:00
Haohan Yang 044d46c36d chore: replace unmatchedEmailAndPasswordError with unmatchedUsernameAndPasswordError` (#3889)
replace unmatchedEmailAndPasswordError with unmatchedUsernameAndPasswordError
2024-09-07 23:17:20 +08:00
Steven 88db037204 chore: fix linter warnings 2024-09-04 23:31:28 +08:00
Steven 4209575244 chore: tweak folder naming style 2024-09-04 23:29:18 +08:00
onee-only b664653306 test: add test for searching memos by tags (#3876) 2024-09-04 12:14:17 +08:00
Leo 95939ebcf1 fix: v0.22.5: start fail caused by incorrect migration file naming (#3873)
fix incorrect naming of migration file
2024-09-04 06:28:55 +08:00
Steven 9612c302c4 chore: bump version to v0.22.5 2024-09-03 22:17:46 +08:00
Steven 773ab96bd0 chore: update thumbnail generator 2024-09-03 22:09:02 +08:00
johnnyjoy 09586d032c chore: fix user checks 2024-09-03 20:48:23 +08:00
Steven fe01d68d2a fix: user role checks 2024-09-03 08:07:31 +08:00
johnnyjoy 5bbf57ece4 chore: update comments of find memo 2024-09-02 21:27:55 +08:00
johnnyjoy c5ef5b9040 chore: update readme 2024-09-02 21:25:42 +08:00
Johnny 971128af05 revert: chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3870)
Revert "chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3862)"

This reverts commit d13bb7648b.
2024-09-02 21:10:54 +08:00
johnnyjoy 40d59fc47a chore: fix user role checks 2024-09-02 21:04:25 +08:00
johnnyjoy 7a9f61967d feat: allow admin users to update other memos 2024-09-02 20:59:22 +08:00
johnnyjoy 8c6682bd77 chore: regenerate apidocs 2024-09-02 20:50:59 +08:00
dependabot[bot] d13bb7648b chore: bump mermaid from 10.9.1 to 11.0.2 in /web (#3862)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 11.0.2.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...mermaid@11.0.2)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 20:46:36 +08:00
dependabot[bot] 0b1ca218ce chore: bump lucide-react from 0.419.0 to 0.437.0 in /web (#3860)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.419.0 to 0.437.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.437.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:54 +08:00
dependabot[bot] 7bce4f5d7b chore: bump @types/react from 18.3.4 to 18.3.5 in /web (#3859)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.4 to 18.3.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:45 +08:00
dependabot[bot] c018af6249 chore: bump @types/node from 22.5.0 to 22.5.2 in /web (#3858)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.0 to 22.5.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:34 +08:00
dependabot[bot] 45d45d0936 chore: bump @bufbuild/buf from 1.38.0 to 1.39.0 in /web (#3861)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.38.0 to 1.39.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.38.0...v1.39.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:07:18 +08:00
dependabot[bot] 04fad85afe chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.21.0 to 2.22.0 (#3863)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.21.0 to 2.22.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.21.0...v2.22.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:06:52 +08:00
dependabot[bot] a654b12670 chore: bump golang.org/x/mod from 0.19.0 to 0.20.0 (#3864)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.19.0 to 0.20.0.
- [Commits](https://github.com/golang/mod/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:03:01 +08:00
dependabot[bot] 2fac11936b chore: bump golang.org/x/oauth2 from 0.21.0 to 0.22.0 (#3866)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:02:53 +08:00
dependabot[bot] acc6c29d01 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.9 to 1.17.16 (#3867)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.9 to 1.17.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.17.9...credentials/v1.17.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 09:20:36 +08:00
Steven be25fbe185 chore: tweak readme 2024-09-02 09:20:14 +08:00
Steven 4322bfa506 chore: tweak seed data 2024-09-01 22:51:02 +08:00
Steven fa2b01cfb1 chore: tweak latest schema file name 2024-09-01 22:11:15 +08:00
aqyuki 35b0bd82f4 chore: migrate of Docker compose v2 (#3857)
chore: rename docker-compose.yaml and remove deprecated field
2024-09-01 22:08:57 +08:00
RoccoSmit bfe57b9202 chore: set max thumbnail width to home/explore image max width (#3852)
* Set max thumbnail width to timeline img max width

* Prevent images less than thumbnail size from being scaled up

* Apply suggestions from code review

---------

Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2024-08-31 03:37:07 +08:00
aqyuki 0156c7e11f perf: reduce image size by 21.3MB (#3849)
- Change base image to distroless (static-debian12)
- Remove unnecessary RUN instructions
- Add build options
  - add options to delete debug information
  - add options to remobe embedded paths
2024-08-30 19:36:34 +08:00
Steven 960af444fa chore: fix linter 2024-08-30 08:25:06 +08:00
Steven 20570fc771 refactor: resource thumbnail 2024-08-30 08:09:07 +08:00
RoccoSmit 9b1adfbbe9 feat: reintroducing thumbnails (#3821)
* Reintroducing thumbnails

* Aligned with linting rules

* making recomended code review change
- changed method names to start with lower case as they are not used outside of their package
- made receiver types for struct funcs to be pointers to not need to create copies

Trying to cover all linting issues
- converted slog warning to use attributes when logging warnings
- seperated imports to have package files in their own section

* Update go.mod

---------

Co-authored-by: boojack <24653555+boojack@users.noreply.github.com>
2024-08-29 21:01:57 +08:00
Steven 615aa94793 fix: base path of migrator 2024-08-29 20:40:50 +08:00
Steven 710961d336 chore: fix text color in dark mode 2024-08-29 20:39:24 +08:00
Steven bb86482b71 chore: tweak setting name 2024-08-29 08:28:11 +08:00
Steven f0abd792c7 chore: update auth service 2024-08-29 00:06:15 +08:00
Steven 1167df29d8 feat: add security related settings 2024-08-28 23:46:06 +08:00
Steven 4e5810e205 chore: update workspace setting section 2024-08-28 23:29:30 +08:00
Steven a8ea28066e chore: retire export memos 2024-08-28 23:20:32 +08:00
Steven 9bea6e1eea chore: go mod tidy 2024-08-28 22:56:17 +08:00
Michel Heusschen 2dbf92f7f1 perf: reduce bundle size by 21% with direct icon imports (#3844) 2024-08-28 22:55:28 +08:00
Steven d11bd30ec6 chore: tweak logger 2024-08-28 22:53:57 +08:00
Steven de980fb7d7 chore: update setting display name 2024-08-28 22:44:13 +08:00
Steven cce92f513c chore: tweak readme 2024-08-27 23:44:03 +08:00
Steven 7134ad4883 chore: fix migration history 2024-08-27 09:20:23 +08:00
Steven fbdfaf85d9 chore: update migrator 2024-08-26 22:50:46 +08:00
Steven ccd3fdcd38 chore: fix tests 2024-08-26 08:59:35 +08:00
Steven 70837f88cb chore: fix linter 2024-08-26 08:47:29 +08:00
Steven 525223c261 chore: add tests for migrator 2024-08-26 08:41:26 +08:00
Steven 96b9269cd3 chore: fix golangci linter 2024-08-24 22:38:22 +08:00
Steven 80f9b5b861 chore: fix golangci linter 2024-08-24 22:30:41 +08:00
Steven fb23f43431 chore: update golangci config 2024-08-24 20:39:46 +08:00
RoccoSmit eca9649be3 fix: cancel removes memo cache (#3826)
Clear local storage record of memo changes if chanes to a memo are cancelled
2024-08-24 06:48:16 +08:00
Steven 5f35ac5ca0 chore: update frontend dependencies 2024-08-22 23:38:11 +08:00
Steven b376a20fb4 chore: tweak linter warnings 2024-08-20 08:25:34 +08:00
Steven 2999f472dd chore: fix typo 2024-08-20 08:17:27 +08:00
Steven 45ddd05c42 chore: tweak linter warning 2024-08-20 08:13:52 +08:00
Steven d1280bc04f chore: implement memo property runner 2024-08-20 08:07:48 +08:00
Steven f4d6675363 chore: add enable memo comment setting 2024-08-19 09:13:44 +08:00
Steven 3c5aa41a78 feat: implement week start day setting 2024-08-18 23:18:45 +08:00
Steven 06c460b476 chore: tweak linter warning 2024-08-16 08:15:59 +08:00
Steven 07012e3f60 chore: remove unused files 2024-08-16 08:14:02 +08:00
Steven 1b6685d7cf chore: tweak linter warning 2024-08-16 08:12:09 +08:00
Steven 710d1b304e chore: update dev mode 2024-08-16 08:08:26 +08:00
Steven 6e901fc940 refactor: store migrator 2024-08-16 08:07:30 +08:00
Steven 1ae3afc0ba chore: tweak memo relation popover 2024-08-14 23:15:04 +08:00
Jakub Wołynko 18db78172c feat: add translation for collapse/expand button and update polish locale (#3811)
add: collapse, expand, polish locale
2024-08-14 18:02:02 +08:00
Steven aae3e8ae64 chore: update memo property checks 2024-08-13 23:29:40 +08:00
Steven 506d2ed8ca chore: tweak menu style 2024-08-13 23:28:02 +08:00
Steven c3f381c8c5 chore: add instance url to profile 2024-08-13 22:16:43 +08:00
Steven 9a27fdf855 chore: tweak load more button 2024-08-12 23:52:23 +08:00
Steven fc2cd43dc2 chore: tweak util tests 2024-08-12 23:44:04 +08:00
Mykal Machon c0826c43b0 fix: explicitly disabling autocapitalize and spellcheck (#3797)
fix #3747: removing autocapitalize and spellcheck
2024-08-12 12:24:37 +08:00
Steven 724db203f7 chore: tweak seed data 2024-08-08 23:45:26 +08:00
Steven 04b4fa1d02 chore: tweak icon button container 2024-08-07 22:56:47 +08:00
Steven 61b8cee31d chore: retire preview markdown dialog 2024-08-07 22:48:16 +08:00
Steven 4ad6028681 refactor: use popover instead of dialog for memo relations 2024-08-07 22:44:39 +08:00
tiltshiftfocus a5978e7657 fix: tag query for mysql (#3785) 2024-08-06 13:56:44 +08:00
Steven 158745704e feat: add memo display setting menu 2024-08-03 01:22:40 +08:00
dependabot[bot] 01819610c7 chore: bump modernc.org/sqlite from 1.30.2 to 1.31.1 (#3769)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.2 to 1.31.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.2...v1.31.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:14:15 +08:00
dependabot[bot] bc5e0b5daf chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.8 to 1.17.9 (#3770)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.8 to 1.17.9.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.8...config/v1.17.9)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:14:05 +08:00
dependabot[bot] 4924af5235 chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.20.0 to 2.21.0 (#3771)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.20.0 to 2.21.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.20.0...v2.21.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:55 +08:00
dependabot[bot] 12a9165852 chore: bump react-router-dom from 6.25.1 to 6.26.0 in /web (#3772)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.26.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:44 +08:00
dependabot[bot] 1fcb867e0f chore: bump react-i18next from 14.1.3 to 15.0.0 in /web (#3774)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 14.1.3 to 15.0.0.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v14.1.3...v15.0.0)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:35 +08:00
dependabot[bot] 222e9dfe58 chore: bump @types/node from 20.14.13 to 22.0.2 in /web (#3775)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.13 to 22.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:13:26 +08:00
dependabot[bot] 55a2e791aa chore: bump lucide-react from 0.399.0 to 0.419.0 in /web (#3773)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.399.0 to 0.419.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.419.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 08:01:36 +08:00
Steven 21f18f7c56 chore: tweak activity service definition 2024-08-01 23:40:16 +08:00
Steven cc91b1e512 chore: buf generate 2024-08-01 22:03:07 +08:00
Steven 26fa172641 chore(frontend): add order by time asc 2024-07-31 23:51:20 +08:00
Steven 6184375cbb chore: upgrade frontend dependencies 2024-07-31 23:51:00 +08:00
Steven 07667257d5 feat: support order by time asc 2024-07-31 23:34:00 +08:00
Steven ea70dd85bf chore: remove color in manifest 2024-07-31 23:09:13 +08:00
Steven 14194504ee chore: remove unused classnames 2024-07-29 23:12:27 +08:00
Steven 444ccc03ed chore: tweak default title 2024-07-29 23:09:46 +08:00
Noah Alderton 117077ac8f fix: dead link in README.md (#3750) 2024-07-28 17:41:47 +08:00
Steven 342b6ad696 chore: tweak seed data 2024-07-27 22:12:43 -04:00
Steven a948555166 fix: release action 2024-07-27 21:21:09 -04:00
Steven 4870433289 chore: tweak release action 2024-07-27 21:07:15 -04:00
Steven a1083e648f chore: fix resource display time 2024-07-27 20:54:42 -04:00
Steven 4b415e519e chore: tweak demo data 2024-07-28 00:24:16 +08:00
Steven 7564c40c8d chore: fix env init 2024-07-27 23:08:22 +08:00
Steven 8fd5365ac1 chore: tweak linter error 2024-07-27 22:19:53 +08:00
Steven a50f3b9382 chore: fix memos sorting 2024-07-27 22:15:47 +08:00
Steven 5ad00c3a50 chore: fix env binding 2024-07-27 21:57:13 +08:00
Steven 8bf7cdfd31 feat: add password auth flag 2024-07-27 19:24:37 +08:00
Steven b9006f8ce0 chore: tweak date utils 2024-07-27 17:21:22 +08:00
Steven 3d63d9d5fb chore: fix activity stats 2024-07-27 10:11:41 +08:00
Steven 139090fb8f chore: fix calendar timestamps 2024-07-27 09:47:12 +08:00
Steven bdc257d837 chore: tweak release actions 2024-07-26 23:30:16 +08:00
Andrew Williams c9c40bc876 chore: build release containers from tags rather than branches (#3739)
Fixes #3645, currently the release containers are build from the release branches, which are created in preparation for a release. This causes some users with automated CI/CD to either deploy a pre-release version or be notified of a release version before it has actually been released. 

This change switches the workflow to be triggered by tags, which are created on the release version.
2024-07-26 10:36:34 +08:00
Steven edc3b578d6 feat: implement search multi tags 2024-07-26 08:40:40 +08:00
Steven c6a09d9353 chore: update memo filter styles 2024-07-26 08:30:59 +08:00
Steven cd38ec93ed feat: implement memo filters 2024-07-26 00:46:48 +08:00
Steven b3b4aa9ddb chore: remove unused code 2024-07-24 23:53:07 +08:00
Steven c5900b355e chore: tweak signup checks 2024-07-24 23:38:51 +08:00
Steven 553e8d09dd chore: update public default value to false 2024-07-24 23:34:19 +08:00
Steven 22ec0cf2e3 chore: bump version 2024-07-23 22:11:53 +08:00
Steven 44e56844f5 chore: tweak search resources 2024-07-22 15:33:02 +08:00
dependabot[bot] 95fa145665 chore: bump @types/node from 20.14.9 to 20.14.11 in /web (#3726)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.9 to 20.14.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 15:32:35 +08:00
dependabot[bot] 84e2d40481 chore: bump @typescript-eslint/parser from 7.16.0 to 7.16.1 in /web (#3727)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.16.0 to 7.16.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:36 +08:00
dependabot[bot] 582c360787 chore: bump dayjs from 1.11.11 to 1.11.12 in /web (#3728)
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.11 to 1.11.12.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.11...v1.11.12)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:26 +08:00
dependabot[bot] 756470099f chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.7 to 1.17.8 (#3729)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.7 to 1.17.8.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.8/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.7...v1.17.8)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:15 +08:00
dependabot[bot] 0a6d7387d1 chore: bump vite from 5.3.1 to 5.3.4 in /web (#3730)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.1 to 5.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:05:01 +08:00
dependabot[bot] 511178389b chore: bump eslint-plugin-prettier from 5.1.3 to 5.2.1 in /web (#3731)
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.3 to 5.2.1.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.3...v5.2.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:49 +08:00
dependabot[bot] e5c214ba5c chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.26 to 1.27.27 (#3732)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.26 to 1.27.27.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.26...config/v1.27.27)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:23 +08:00
dependabot[bot] 7e7786077f chore: bump google.golang.org/grpc from 1.64.0 to 1.65.0 (#3733)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.65.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.65.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:11 +08:00
dependabot[bot] 5f58bb368b chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.26 to 1.17.27 (#3734)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.26 to 1.17.27.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.26...credentials/v1.17.27)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 09:57:59 +08:00
Steven c313596144 feat: update memo editor 2024-07-22 09:57:40 +08:00
Johnny d2727e6825 chore: update dependabot schedule interval (#3725) 2024-07-21 20:49:42 +08:00
Steven 10c9bb081b chore: retire timeline page 2024-07-20 00:28:49 +08:00
Steven 17ecfb5cf5 fix: acl config 2024-07-19 20:54:51 +08:00
Steven c4a24bead6 chore(frontend): tweak memo relations 2024-07-19 20:52:52 +08:00
andrigamerita d264f45979 fix: code blocks of unknown languages cause HTML injection (#3711)
* fix: code blocks of unknown languages cause HTML injection

A code block of unknown language (that is, a language not treated as special by Memos and not handled by highlight.js) should fall back on rendering its plaintext content. However, the content is never properly escaped before it is appended to the DOM, and thus any string that happens to contain HTML is unsafely rendered. This commit fixes the issue by ensuring that, when none of the previous cases handle the text, any HTML entities are escaped first.

* Update CodeBlock.tsx to conform to eslint
2024-07-19 08:32:58 +08:00
andrigamerita af952807c7 feat: write memo UID in file names when exporting to Markdown (#3712)
When using the "export to Markdown" feature in Memos, the files included in the ZIP folder don't feature any kind of reference to their alphanumeric UID from the server's database, which completely breaks the point of links inside the files made with the `[[memos/<uid>]]` format, since it's impossible to know which Markdown file this kind of string inside other files refers to.

This pull request modifies the ExportMemos server function, to add the UID of every memo immediately after the date in the filename. For example, an exported memo would now be called: `YYYY-MM-DDThh:mm:ss+hh:mm-AbcDefGhiJklMnoPqrStu1-PUBLIC.md`.
2024-07-19 07:14:31 +08:00
Steven fefe2b0655 chore: fix build artifacts action 2024-07-17 23:16:09 +08:00
Steven 5704aaad08 chore: tweak embeded memo style 2024-07-17 22:48:22 +08:00
Steven ef7e2151dc chore: update memo relation list 2024-07-17 21:40:43 +08:00
Steven e2fd79200e feat: implement inline memo editor 2024-07-17 21:07:36 +08:00
Steven 956f21838d chore: fix popover z-index 2024-07-17 20:28:31 +08:00
Steven 878fea5f13 chore: use popover for update tag view setting 2024-07-17 08:46:52 +08:00
Steven 5a26b76511 chore: add memo content snippet 2024-07-17 08:18:37 +08:00
dependabot[bot] 0053977b14 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.24 to 1.27.26 (#3691)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.24 to 1.27.26.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.24...config/v1.27.26)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:26:20 +08:00
dependabot[bot] e5c7571eb5 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.4 to 1.17.7 (#3690)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.4 to 1.17.7.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.7/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.4...v1.17.7)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:26:06 +08:00
dependabot[bot] daca7193b5 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.24 to 1.17.26 (#3693)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.24 to 1.17.26.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.24...credentials/v1.17.26)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:24:48 +08:00
dependabot[bot] ca1d3b6eb1 chore: bump modernc.org/sqlite from 1.30.1 to 1.30.2 (#3692)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.1 to 1.30.2.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.1...v1.30.2)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:24:34 +08:00
dependabot[bot] fcdca5b270 chore: bump github.com/aws/aws-sdk-go-v2 from 1.30.1 to 1.30.3 (#3694)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.30.1 to 1.30.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.30.1...v1.30.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:46 +08:00
dependabot[bot] 07f79b9f7a chore: bump @mui/joy from 5.0.0-beta.36 to 5.0.0-beta.48 in /web (#3695)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.36 to 5.0.0-beta.48.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:26 +08:00
dependabot[bot] 41d9d3bc21 chore: bump prettier from 3.3.2 to 3.3.3 in /web (#3696)
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.2...3.3.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:23:01 +08:00
dependabot[bot] fae951ae2b chore: bump @typescript-eslint/eslint-plugin from 7.15.0 to 7.16.0 in /web (#3697)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.15.0 to 7.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 22:22:44 +08:00
Steven 446e38f15b fix: memo content snippet 2024-07-16 22:19:48 +08:00
dependabot[bot] 7c9f967a07 chore: bump dompurify from 3.1.5 to 3.1.6 in /web (#3698)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.5...3.1.6)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 09:43:40 +08:00
dependabot[bot] a5d36655e9 chore: bump tailwindcss from 3.4.4 to 3.4.5 in /web (#3699)
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.4 to 3.4.5.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.5/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.5)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 09:43:29 +08:00
Steven f2cfc528a6 chore: introduce tag view option 2024-07-15 22:55:59 +08:00
Steven 260a4f89fc chore: buf generate 2024-07-15 22:32:59 +08:00
Johnny 9909fd8a6f feat: add snippet field to memo message (#3689) 2024-07-15 08:08:08 +08:00
Johnny bcb8843245 chore: implement stringify markdown nodes endpoint (#3688) 2024-07-14 20:46:57 +08:00
Johnny 7c9e54afbd chore: update disallow public visibility setting name (#3687) 2024-07-14 20:23:19 +08:00
Steven 6825c1def4 fix: delete access token when sign out 2024-07-13 11:18:29 +08:00
Steven f374169a2b feat: implement html element renderer 2024-07-13 11:06:51 +08:00
Johnny 4ff3b89a8e chore: update i18n from Weblate (#3680)
* Added translation using Weblate (Catalan)

* Translated using Weblate (Catalan)

Currently translated at 25.0% (65 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ca/

* Translated using Weblate (French)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

---------

Co-authored-by: Carles Mateu <carlesm@carlesm.com>
Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-07-12 22:22:59 +08:00
Johnny 5a196e2f1a feat: update gomark version (#3679) 2024-07-12 22:17:03 +08:00
Steven 9449886d60 chore: fix linter 2024-07-12 08:36:55 +08:00
Steven 457cf92cc1 feat(api): implement get resource by uid 2024-07-11 23:43:44 +08:00
Steven 1ab2c89408 feat(api): implement get memo by uid 2024-07-11 23:31:50 +08:00
dependabot[bot] 34e938a1e3 chore: bump typescript from 5.5.2 to 5.5.3 in /web (#3664)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.5.2 to 5.5.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.5.2...v5.5.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 23:00:45 +08:00
dependabot[bot] b265445068 chore: bump golang.org/x/net from 0.26.0 to 0.27.0 (#3669)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:52 +08:00
dependabot[bot] 37d13b5cbc chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.23 to 1.27.24 (#3667)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.23 to 1.27.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.23...config/v1.27.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:45 +08:00
dependabot[bot] fb4fdb326a chore: bump golang.org/x/crypto from 0.24.0 to 0.25.0 (#3668)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/crypto/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:26 +08:00
dependabot[bot] 5623a0f065 chore: bump @typescript-eslint/parser from 7.14.1 to 7.16.0 in /web (#3672)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.14.1 to 7.16.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.16.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:12 +08:00
dependabot[bot] b220f14bec chore: bump katex from 0.16.10 to 0.16.11 in /web (#3663)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.10 to 0.16.11.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.10...v0.16.11)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 22:59:03 +08:00
dependabot[bot] 3e4b33fb28 chore: bump highlight.js from 11.9.0 to 11.10.0 in /web (#3665)
Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 11.9.0 to 11.10.0.
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/main/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/11.9.0...11.10.0)

---
updated-dependencies:
- dependency-name: highlight.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:13:36 +08:00
dependabot[bot] 08a43d0faa chore: bump @typescript-eslint/eslint-plugin from 7.14.1 to 7.15.0 in /web (#3666)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.14.1 to 7.15.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.15.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:13:24 +08:00
dependabot[bot] 36795abacc chore: bump golang.org/x/mod from 0.18.0 to 0.19.0 (#3670)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/mod/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:12:49 +08:00
dependabot[bot] 9f7295a4ee chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.23 to 1.17.24 (#3671)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.23 to 1.17.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.23...credentials/v1.17.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 18:12:39 +08:00
Steven 626c972d9c chore: add properties to memo detail sidebar 2024-07-08 23:14:00 +08:00
Johnny 5e3ed201b4 fix: update mask of update memo (#3659) 2024-07-08 08:50:38 +08:00
Johnny eccddb1154 chore: add create time to memo detail sidebar (#3657) 2024-07-07 23:09:48 +08:00
dependabot[bot] a681b8e205 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.21 to 1.27.23 (#3640)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.21 to 1.27.23.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.21...config/v1.27.23)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-06 16:48:24 +08:00
dependabot[bot] 881809926e chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.17.1 to 1.17.4 (#3649)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.17.1 to 1.17.4.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.4/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.17.1...v1.17.4)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-06 16:48:15 +08:00
Johnny a98d16bcaa chore: update bug report template fields (#3656) 2024-07-06 14:16:44 +08:00
dependabot[bot] 46ca5bb8e7 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.21 to 1.17.23 (#3637)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.21 to 1.17.23.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.21...credentials/v1.17.23)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-03 11:44:04 +08:00
dependabot[bot] b1f12d54a0 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.56.1 to 1.57.1 (#3644)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.56.1 to 1.57.1.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.56.1...service/s3/v1.57.1)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 23:15:39 +08:00
Johnny 4d2b953e23 chore: add enable link preview setting to memo related settings (#3647) 2024-07-02 22:00:38 +08:00
dependabot[bot] b57b6bae34 chore: bump postcss from 8.4.38 to 8.4.39 in /web (#3642)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.38 to 8.4.39.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.38...8.4.39)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:51 +08:00
dependabot[bot] 90c67d5592 chore: bump @typescript-eslint/eslint-plugin from 7.13.1 to 7.14.1 in /web (#3641)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.13.1 to 7.14.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.14.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:38 +08:00
dependabot[bot] 4655c99c4e chore: bump @bufbuild/buf from 1.33.0 to 1.34.0 in /web (#3639)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.33.0 to 1.34.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.33.0...v1.34.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:24 +08:00
dependabot[bot] 68e924e48c chore: bump @types/node from 20.14.2 to 20.14.9 in /web (#3638)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.2 to 20.14.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:13 +08:00
dependabot[bot] ee61bc7861 chore: bump react-router-dom from 6.23.1 to 6.24.0 in /web (#3636)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.23.1 to 6.24.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.24.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 08:25:02 +08:00
Steven 3782d412f5 chore: upgrade gomark 2024-07-01 23:28:36 +08:00
dependabot[bot] de754079cc chore: bump zustand from 4.5.2 to 4.5.4 in /web (#3632)
Bumps [zustand](https://github.com/pmndrs/zustand) from 4.5.2 to 4.5.4.
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v4.5.2...v4.5.4)

---
updated-dependencies:
- dependency-name: zustand
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:41 +08:00
dependabot[bot] df0dcb553b chore: bump typescript from 5.4.5 to 5.5.2 in /web (#3633)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.5 to 5.5.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.5...v5.5.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:33 +08:00
dependabot[bot] 584d73659e chore: bump @reduxjs/toolkit from 2.2.5 to 2.2.6 in /web (#3634)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.5 to 2.2.6.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.5...v2.2.6)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:27:22 +08:00
dependabot[bot] 122710801a chore: bump protobufjs from 7.3.0 to 7.3.2 in /web (#3631)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.3.0 to 7.3.2.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.3.0...protobufjs-v7.3.2)

---
updated-dependencies:
- dependency-name: protobufjs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:24:33 +08:00
Steven 1ad5d9bf0a chore: update confirm dialog 2024-07-01 23:22:39 +08:00
dependabot[bot] 4a3afffeef chore: bump lucide-react from 0.396.0 to 0.399.0 in /web (#3630)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.396.0 to 0.399.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.399.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 23:13:52 +08:00
Steven 291b815653 feat: implement memo detail sidebar 2024-07-01 23:06:10 +08:00
Steven 05c6edfe2f chore: tweak auth pages 2024-06-26 22:11:18 +08:00
dependabot[bot] 6325b3eef9 chore: bump @types/uuid from 9.0.8 to 10.0.0 in /web (#3616)
Bumps [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid) from 9.0.8 to 10.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/uuid)

---
updated-dependencies:
- dependency-name: "@types/uuid"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:39 +08:00
dependabot[bot] 80c57692e9 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.24 to 1.17.1 (#3617)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.24 to 1.17.1.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.1/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.24...v1.17.1)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:29 +08:00
dependabot[bot] 5828632613 chore: bump @typescript-eslint/parser from 7.13.0 to 7.14.1 in /web (#3620)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.13.0 to 7.14.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.14.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:11:18 +08:00
Roman Lomonosov b923988fd6 fix: can't change memo UID (#3621) 2024-06-26 07:18:00 +08:00
dependabot[bot] 9b090d909e chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.18 to 1.27.21 (#3612)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.18 to 1.27.21.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.18...config/v1.27.21)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:31:27 +08:00
dependabot[bot] 6abc272709 chore: bump lucide-react from 0.395.0 to 0.396.0 in /web (#3614)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.395.0 to 0.396.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.396.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:31:12 +08:00
dependabot[bot] 3752e7b638 chore: bump eslint-plugin-react from 7.34.2 to 7.34.3 in /web (#3618)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.34.2 to 7.34.3.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.34.2...v7.34.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:30:56 +08:00
dependabot[bot] 9ba2adb4c4 chore: bump @typescript-eslint/eslint-plugin from 7.13.0 to 7.13.1 in /web (#3619)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.13.0 to 7.13.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 22:30:39 +08:00
Zeng1998 4f4fe9b26b fix: add charset=utf-8 for text content resources (#3608)
Co-authored-by: = <=>
2024-06-24 23:01:19 +08:00
Johnny ca463891f2 chore: fix linter warning for slog (#3604) 2024-06-22 16:39:40 +08:00
Mudkip e33244e64b fix: PATCH requests on /api/v1 not working (#3600)
* fix: PATCH requests on /api/v1

* Update server/server.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-06-21 18:16:55 +08:00
steven 33cd3ed8e3 chore: bump version 2024-06-21 18:16:35 +08:00
Ryo a09c669865 fix: allow cors for grpc gateway handler (#3574) 2024-06-21 18:13:59 +08:00
dependabot[bot] 759337996f chore: bump lucide-react from 0.383.0 to 0.395.0 in /web (#3584)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.383.0 to 0.395.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.395.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:11:05 +08:00
dependabot[bot] cee1d4b1ed chore: bump @typescript-eslint/eslint-plugin from 7.12.0 to 7.13.0 in /web (#3585)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 7.12.0 to 7.13.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:51 +08:00
dependabot[bot] 77b92f675a chore: bump @bufbuild/buf from 1.32.2 to 1.33.0 in /web (#3586)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.32.2 to 1.33.0.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.32.2...v1.33.0)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:38 +08:00
dependabot[bot] 795700b161 chore: bump vite from 5.2.13 to 5.3.1 in /web (#3587)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.13 to 5.3.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:28 +08:00
dependabot[bot] 513ff9d2b0 chore: bump prettier from 3.3.1 to 3.3.2 in /web (#3588)
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:10:10 +08:00
dependabot[bot] 84692404e1 chore: bump golang.org/x/oauth2 from 0.20.0 to 0.21.0 (#3583)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.20.0 to 0.21.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:09:34 +08:00
dependabot[bot] d5d0d14728 chore: bump github.com/gorilla/feeds from 1.1.2 to 1.2.0 (#3582)
Bumps [github.com/gorilla/feeds](https://github.com/gorilla/feeds) from 1.1.2 to 1.2.0.
- [Release notes](https://github.com/gorilla/feeds/releases)
- [Commits](https://github.com/gorilla/feeds/compare/v1.1.2...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/gorilla/feeds
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:09:02 +08:00
dependabot[bot] 9bec88eedc chore: bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#3581)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:53 +08:00
dependabot[bot] 1bf6db8154 chore: bump google.golang.org/protobuf from 1.34.1 to 1.34.2 (#3580)
Bumps google.golang.org/protobuf from 1.34.1 to 1.34.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:42 +08:00
dependabot[bot] 5fb649c3c3 chore: bump modernc.org/sqlite from 1.30.0 to 1.30.1 (#3579)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.0 to 1.30.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.0...v1.30.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:30 +08:00
dependabot[bot] b911e98e37 chore: bump docker/build-push-action from 5 to 6 (#3578)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 22:08:20 +08:00
Steven 0501f5198a chore: buf format 2024-06-19 22:07:51 +08:00
Johnny 736637a362 feat: add public flag instead of system setting to enable signup (#3589) 2024-06-19 22:03:12 +08:00
Steven 387bf48fc8 chore: update s3 config 2024-06-11 22:05:28 +08:00
dependabot[bot] e9d027ca3e chore: bump @typescript-eslint/parser from 7.12.0 to 7.13.0 in /web (#3558)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.12.0 to 7.13.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.13.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 10:48:03 +08:00
dependabot[bot] 0c378ec291 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.21 to 1.16.24 (#3547)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.21 to 1.16.24.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.21...service/ram/v1.16.24)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 09:01:47 +08:00
dependabot[bot] 5836bf5a72 chore: bump golang.org/x/net from 0.25.0 to 0.26.0 (#3549)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0.
- [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:43 +08:00
dependabot[bot] 7aba6bef21 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.16 to 1.27.18 (#3550)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.16 to 1.27.18.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.16...config/v1.27.18)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:32 +08:00
dependabot[bot] f31a53caa7 chore: bump uuid from 9.0.1 to 10.0.0 in /web (#3556)
Bumps [uuid](https://github.com/uuidjs/uuid) from 9.0.1 to 10.0.0.
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.1...v10.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-11 08:59:08 +08:00
dependabot[bot] 28624514d1 chore: bump goreleaser/goreleaser-action from 5 to 6 (#3551)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 5 to 6.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:35:09 +08:00
dependabot[bot] b42979edcc chore: bump golang.org/x/mod from 0.17.0 to 0.18.0 (#3548)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/mod/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:34:45 +08:00
dependabot[bot] bc1b095812 chore: bump github.com/aws/aws-sdk-go-v2 from 1.27.0 to 1.27.2 (#3546)
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.27.0 to 1.27.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.27.0...v1.27.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 23:34:24 +08:00
Ryo 2c819ace4e feat: return not found error instead internal error for local file not exist (#3543)
* chore: add `/.vscode` to `.gitignore`

* feat: return not found instead of internal for resource

* feat: check file not exist only if error not nil
2024-06-10 14:11:28 +08:00
andrigamerita e4a09c407c feat: write memo visibility in file names when exporting (#3538)
When using the dedicated feature in Memos' user settings to export all memos to Markdown files inside a ZIP folder, the output doesn't feature any kind of distinction for memos by their set visibility.
While this is not a big issue for personal backups, it can reveal itself problematic if exporting the data to share it with other people, or maybe deploy to a static site generator, because there is nothing in the files that distinguishes public memos from private or workspace-restricted ones.

This pull request simply modifies the ExportMemos server function, to add the Visibility status to the end of every exported file name inside the ZIP, right after the date (which is left intact). For example, the file for a public memo would now be called: `YYYY-MM-DDThh:mm:ss+hh:mm-PUBLIC.md`.

An alternative solution would have been to write this information in a YAML header at the beginning of every Markdown file, but, since those are not used anywhere else in the software, I decided to stick with what is already used for export metadata, the filename.
2024-06-09 19:22:13 +08:00
Steven da603053f2 chore: add th locale 2024-06-09 07:46:03 +08:00
boojack edda6ea4bd chore: update i18n with Weblate (#3540)
* Added translation using Weblate (Thai)

* Translated using Weblate (Thai)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/th/

---------

Co-authored-by: NeneNeko <lennon.rin@gmail.com>
2024-06-09 07:43:59 +08:00
boojack 7b7ecc2daa chore: update i18n with Weblate (#3533)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Yuri <isyuricunha@duck.com>
2024-06-07 05:10:12 +08:00
Steven fa4521e0c5 chore: update gomark source 2024-06-06 23:09:13 +08:00
Steven 076aa2f8aa chore: remove memo filter 2024-06-05 23:18:14 +08:00
Steven f33571fec6 feat: update webhook request payload 2024-06-05 20:53:20 +08:00
Steven d159975994 chore: update statistics view 2024-06-05 20:46:35 +08:00
Martin MacDonald aec5927d31 feat: add hook for generating different date times (#3524)
* Added hook for generating different date times

* Fixed up logic to destructure the datetime params

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 19:52:07 +08:00
Steven 7375b87967 chore: tweak tooltips 2024-06-05 08:51:04 +08:00
Steven 54539aa047 chore: tweak seed data 2024-06-05 08:48:46 +08:00
Steven d0ac866eb1 chore: update statistics view 2024-06-05 08:48:40 +08:00
Steven 797f5a123c feat: add HasIncompleteTasks to memo property 2024-06-05 08:39:56 +08:00
Martin MacDonald f0817f2762 chore: update fetch tags args (#3515)
* Centralised the logic for filters to apply to tagging and updated components to pass in those params needed

* Fixed linting issue

* Split out params from options

* Fixed linting errors

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:06:01 +08:00
Martin MacDonald 2ebd5c64bd fix: copy by reference (#3517)
* Fixed issue with copy by reference

* Fixed linting issues

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:04:50 +08:00
Martin MacDonald 0977acbc7f fix: update uniqby key (#3518)
* Used correct uniqby key

* Put back filter

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-05 08:03:56 +08:00
Steven e8ed437ca3 fix: purify html before render 2024-06-04 23:10:54 +08:00
Steven 2b49025f4a chore: update memo filters 2024-06-04 23:03:51 +08:00
Steven bddfe00b5c chore: bump version 2024-06-04 20:51:53 +08:00
dependabot[bot] aafddac65f chore: bump modernc.org/sqlite from 1.29.10 to 1.30.0 (#3510)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.10 to 1.30.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.10...v1.30.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-04 07:18:07 +08:00
dependabot[bot] b4113581b3 chore: bump github.com/spf13/viper from 1.18.2 to 1.19.0 (#3511)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.2 to 1.19.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.2...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-04 07:17:40 +08:00
Steven e40b39033f chore: fix compact default value 2024-06-04 07:17:16 +08:00
Michael 616f306efe chore: update i18n with Weblate (#3509)
* Translated using Weblate (French)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: ti777777 <ti12272198686@yahoo.com.tw>
2024-06-03 23:57:59 +08:00
Steven 370ac32344 chore: regenerate pnpm-local.yaml 2024-06-03 23:51:29 +08:00
Steven 20b8a97a88 chore: retire outdate scripts 2024-06-03 23:50:59 +08:00
dependabot[bot] be6fc1ca4d chore: bump lucide-react from 0.378.0 to 0.383.0 in /web (#3507)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.378.0 to 0.383.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.383.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 23:40:00 +08:00
dependabot[bot] c41d53b4b6 chore: bump @types/node from 20.12.12 to 20.14.0 in /web (#3504)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.12 to 20.14.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 23:38:03 +08:00
Martin MacDonald 760dee4159 feat: delete memo comments when memo is deleted (#3491)
* Added logic to delete memo relation and memo comments recursively when a memo is deleted

* Fixed logic to only target comment types and added removing of broken references

* Fixed linting errors

---------

Co-authored-by: Martin MacDonald <martinmacdonald@Martins-MacBook-Pro.local>
2024-06-03 19:50:13 +08:00
Steven 08d37acffa chore: tweak readme 2024-06-02 14:31:54 +08:00
Michael c484b09c4c chore: update i18n with Weblate (#3499)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (260 of 260 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-06-02 14:06:05 +08:00
Steven 2e0d5412b4 chore: tweak webhook payload 2024-06-01 23:46:00 +08:00
Steven 8c0bee3840 chore: tweak refresh button 2024-06-01 23:27:35 +08:00
Steven 78f6064530 chore: tweak goreleaser action 2024-06-01 10:04:39 +08:00
Steven d7be24a0e1 chore: tweak goreleaser 2024-06-01 09:59:52 +08:00
Steven 5493f5f14e chore: regenerate dependencies 2024-06-01 09:58:47 +08:00
Steven 1dc686fa6c chore: update build artifacts 2024-06-01 09:49:47 +08:00
Steven 4e54ec38ff chore: update memo related settings 2024-06-01 09:05:09 +08:00
Steven 0657a1ef5b chore: fix memo editor cache 2024-06-01 08:48:54 +08:00
Michael 48546f05b3 chore: update i18n with Weblate (#3492)
* Translated using Weblate (Turkish)

Currently translated at 100.0% (259 of 259 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (259 of 259 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Apply suggestions from code review

---------

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-06-01 08:42:01 +08:00
Steven 08a9291964 chore: update timeline filters 2024-05-31 09:06:03 +08:00
Steven 98f2cf6397 chore: tweak linter 2024-05-30 07:23:16 +08:00
Steven b1cc1255bb chore: tweak seed data 2024-05-30 07:21:10 +08:00
Steven b215426623 chore: update general setting 2024-05-30 07:19:38 +08:00
Steven 423861d48c fix: create idp in postgres 2024-05-29 23:22:20 +08:00
Michael f2b708c1b8 chore: update i18n with Weblate (#3483)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (257 of 257 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (257 of 257 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Ramazan SANCAR <ramazansancar4545@gmail.com>
2024-05-29 23:20:11 +08:00
Steven 0f4b7c5f4a feat: add more memo settings 2024-05-29 23:17:53 +08:00
Steven 1894ef161f chore: fix content search 2024-05-29 22:04:37 +08:00
Michael 98eb57b370 chore: update translation files (#3481)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-29 08:05:14 +08:00
Steven cf70867470 chore: update tag section 2024-05-29 08:03:01 +08:00
Steven 719c22fef8 chore: update i18n 2024-05-29 07:39:16 +08:00
Steven 6010139291 chore: remove unused 2024-05-29 07:36:51 +08:00
Steven cbf556fee5 chore: fix memo cache key 2024-05-28 23:23:23 +08:00
Steven 93e848d170 chore: tweak root redirector 2024-05-28 19:59:29 +08:00
Steven 60b5b4815d chore: fix imports 2024-05-28 09:10:08 +08:00
dependabot[bot] 98bd4568e7 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.20 to 1.16.21 (#3469)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.20 to 1.16.21.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.20...service/ram/v1.16.21)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:07:42 +08:00
dependabot[bot] c24225fd89 chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.54.2 to 1.54.3 (#3471)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.54.2 to 1.54.3.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.54.2...service/s3/v1.54.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:06:53 +08:00
dependabot[bot] 5ea04ca596 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.15 to 1.27.16 (#3472)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.15 to 1.27.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.15...config/v1.27.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 09:06:45 +08:00
Steven 0275a65781 chore: add last visited page 2024-05-28 09:05:59 +08:00
dependabot[bot] 239f28c1e0 chore: bump @vitejs/plugin-react from 4.2.1 to 4.3.0 in /web (#3467)
Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/v4.3.0/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 06:07:43 +08:00
dependabot[bot] f78114da43 chore: bump github.com/aws/aws-sdk-go-v2/credentials from 1.17.15 to 1.17.16 (#3468)
chore: bump github.com/aws/aws-sdk-go-v2/credentials

Bumps [github.com/aws/aws-sdk-go-v2/credentials](https://github.com/aws/aws-sdk-go-v2) from 1.17.15 to 1.17.16.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/credentials/v1.17.15...credentials/v1.17.16)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:37:05 +08:00
dependabot[bot] 75e76e1331 chore: bump @types/react from 18.3.2 to 18.3.3 in /web (#3466)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.2 to 18.3.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:53 +08:00
dependabot[bot] 9f83be1d48 chore: bump @typescript-eslint/parser from 7.9.0 to 7.10.0 in /web (#3465)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.9.0 to 7.10.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.10.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:43 +08:00
dependabot[bot] 250bdff4c5 chore: bump @bufbuild/buf from 1.32.0 to 1.32.1 in /web (#3464)
Bumps [@bufbuild/buf](https://github.com/bufbuild/buf) from 1.32.0 to 1.32.1.
- [Release notes](https://github.com/bufbuild/buf/releases)
- [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bufbuild/buf/compare/v1.32.0...v1.32.1)

---
updated-dependencies:
- dependency-name: "@bufbuild/buf"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:33 +08:00
dependabot[bot] b8d4720e5e chore: bump i18next from 23.11.4 to 23.11.5 in /web (#3463)
Bumps [i18next](https://github.com/i18next/i18next) from 23.11.4 to 23.11.5.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.11.4...v23.11.5)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:24 +08:00
dependabot[bot] 3e11adc15b chore: bump modernc.org/sqlite from 1.29.9 to 1.29.10 (#3470)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.9 to 1.29.10.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.9...v1.29.10)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 23:36:09 +08:00
Steven e475f00ba1 chore: tweak seed data 2024-05-27 23:32:08 +08:00
Steven f0e5a72271 feat: update search memo filter 2024-05-27 23:25:25 +08:00
Steven ba0876a563 feat: update statistics view 2024-05-27 20:04:07 +08:00
Steven a423dac12c chore: tweak memo property 2024-05-27 19:43:57 +08:00
Steven 2b4c2b23b2 chore: tweak linter 2024-05-26 21:39:34 +08:00
Ryo 784fcbb698 feat: add panic recovery middleware for grpc and echo server (#3459) 2024-05-26 21:38:59 +08:00
Steven 1ccfa81cf3 chore: tweak common function 2024-05-26 11:02:23 +08:00
Steven a177800e83 chore: tweak error message 2024-05-25 11:05:35 +08:00
Steven d39cacf1f9 chore: tweak readme 2024-05-25 11:01:54 +08:00
Michael 8233a6ba1c chore: translated using Weblate (Marathi) (#3451)
Translated using Weblate (Marathi)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/mr/

Co-authored-by: quaintdev <accounts@rohanrd.xyz>
2024-05-25 05:44:20 +08:00
quaintdev af71ac49bb feat(i18n): added marathi(mr) translations (#3449) 2024-05-25 05:43:37 +08:00
Steven 7d6dbb9487 fix: link hover handler 2024-05-22 23:25:04 +08:00
Steven 4070998f9f chore: fix linter 2024-05-22 21:55:13 +08:00
Steven d3235f75f3 chore: tweak memo definition 2024-05-22 21:52:41 +08:00
Steven e0600388b2 chore: implement memo property endpoint 2024-05-22 09:21:12 +08:00
Steven 16d3de63c2 chore: update resource binary endpoint 2024-05-21 21:25:21 +08:00
Michael 2c50d3469e chore: update i18n with weblate (#3435)
* Translated using Weblate (Ukrainian)

Currently translated at 58.0% (148 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/uk/

* Translated using Weblate (Ukrainian)

Currently translated at 58.0% (148 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/uk/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: Gregory Malets <gregory.malets@gmail.com>
2024-05-21 20:36:28 +08:00
Steven b5d2ff6e28 chore: fix linter 2024-05-21 00:08:57 +08:00
dependabot[bot] 3616194d03 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.17 to 1.16.20 (#3415)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.17 to 1.16.20.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ram/v1.16.17...service/ram/v1.16.20)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:04:02 +08:00
Steven 811c0757c4 chore: fix linter 2024-05-21 00:03:30 +08:00
dependabot[bot] 464b00ea0b chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.53.2 to 1.54.2 (#3416)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.53.2 to 1.54.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.53.2...service/s3/v1.54.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:02:17 +08:00
dependabot[bot] a1e610fd8e chore: bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.19.1 to 2.20.0 (#3417)
chore: bump github.com/grpc-ecosystem/grpc-gateway/v2

Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.19.1 to 2.20.0.
- [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases)
- [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml)
- [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.19.1...v2.20.0)

---
updated-dependencies:
- dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:02:08 +08:00
dependabot[bot] e813853624 chore: bump google.golang.org/grpc from 1.63.2 to 1.64.0 (#3418)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.63.2 to 1.64.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.63.2...v1.64.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:52 +08:00
dependabot[bot] b2f9496c96 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.13 to 1.27.15 (#3414)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.13 to 1.27.15.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.13...config/v1.27.15)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:27 +08:00
dependabot[bot] f1392e220e chore: bump @typescript-eslint/parser from 7.8.0 to 7.9.0 in /web (#3423)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 7.8.0 to 7.9.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.9.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:00:06 +08:00
Steven f37b34544b chore: update user access token checks 2024-05-20 22:32:42 +08:00
Steven f54b05a521 chore: tweak comments 2024-05-20 22:15:51 +08:00
Steven 613c9e9416 chore: tweak version 2024-05-20 21:10:04 +08:00
Steven fb15386db2 chore: remove access token after sign out 2024-05-20 08:53:29 +08:00
Steven 21838d0aae chore: fix editor autocomplete 2024-05-20 08:49:55 +08:00
Timothy 52ebfd703c fix: update resource with id (#3405)
* chore: update presign expires

* fix: update resource with id

---------

Co-authored-by: timothy <timothy123890511@gmail.com>
2024-05-19 23:18:03 +08:00
Michael 8f6d38719f chore: update i18n from Weblate (#3399)
* Added translation using Weblate (Marathi)

* Translated using Weblate (Marathi)

Currently translated at 22.7% (58 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/mr/

---------

Co-authored-by: quaintdev <accounts@rohanrd.xyz>
2024-05-19 09:16:13 +08:00
Steven 93d06bc0f0 chore: tweak readme 2024-05-19 09:15:46 +08:00
Steven c25c57ab61 feat: support updating display time 2024-05-18 07:52:35 +08:00
Steven b0aad6f694 chore: tweak resource payload 2024-05-17 08:50:02 +08:00
Steven 0c251f9ab8 chore: fix resource delete handler 2024-05-16 21:53:12 +08:00
wzc90 0a9212f815 fix: memo find for mysql(#3387)
* Update memo.go

* Update store/db/mysql/memo.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-05-16 07:37:42 +08:00
Steven 537ae622d2 chore: filter inbox type 2024-05-15 23:22:23 +08:00
Steven 3e5e5b1f80 chore: fix search memos 2024-05-15 22:42:31 +08:00
wzc90 3ecbbf31a9 fix: migration scripts for mysql (#3384) 2024-05-15 17:34:59 +08:00
wzc90 deb1deb14c fix: resource create time format for mysql (#3381) 2024-05-15 15:51:43 +08:00
Steven c8ff3fa2ee chore: fix uploading flag 2024-05-15 09:08:34 +08:00
dependabot[bot] f67676ac43 chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager from 1.16.15 to 1.16.17 (#3367)
chore: bump github.com/aws/aws-sdk-go-v2/feature/s3/manager

Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.16.15 to 1.16.17.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.16.15...service/ram/v1.16.17)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:48:46 +08:00
dependabot[bot] 38c6c50681 chore: bump golangci/golangci-lint-action from 5 to 6 (#3365)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5 to 6.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:44 +08:00
dependabot[bot] 74e0f5429a chore: bump pnpm/action-setup from 3.0.0 to 4.0.0 (#3366)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v3.0.0...v4.0.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:35 +08:00
dependabot[bot] 3add70714f chore: bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.53.1 to 1.53.2 (#3369)
chore: bump github.com/aws/aws-sdk-go-v2/service/s3

Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.53.1 to 1.53.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.53.1...service/s3/v1.53.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:46:28 +08:00
dependabot[bot] 78f0ae649a chore: bump golang.org/x/net from 0.24.0 to 0.25.0 (#3370)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/net/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 08:12:52 +08:00
Steven 9265b8e2bd chore: update tags filter 2024-05-14 08:12:25 +08:00
Steven 2317204c50 fix: list idp 2024-05-14 07:04:17 +08:00
dependabot[bot] 32abc50af4 chore: bump github.com/aws/aws-sdk-go-v2/config from 1.27.11 to 1.27.13 (#3371) 2024-05-14 06:45:14 +08:00
Steven 0c673d49ef chore: retire memo tags 2024-05-13 22:12:56 +08:00
Steven d3744ccfa3 chore: tweak seed data 2024-05-13 22:07:44 +08:00
Steven c561362d62 feat: implement memo property 2024-05-13 22:04:37 +08:00
Steven 555b4fbe32 chore: update seed data 2024-05-13 20:27:24 +08:00
Steven 8948edf654 chore: impl memo payload definition 2024-05-13 20:24:11 +08:00
Steven 31e07c083d chore: fix types 2024-05-13 20:07:56 +08:00
Steven b8763905ba chore: tweak naming 2024-05-13 20:03:04 +08:00
Michael 62705fed39 chore: translated using Weblate (French) (#3358)
Translated using Weblate (French)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-05-13 10:18:33 +08:00
Michael 6df3cf808e chore: update seed data 2024-05-13 10:15:30 +08:00
Michael 6c481743de chore: translated using Weblate (Turkish) (#3356)
Translated using Weblate (Turkish)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-05-13 08:10:15 +08:00
Steven 83b9ea45b9 chore: tweak dark mode styles 2024-05-13 08:09:32 +08:00
Steven f79554371d chore: retire share dialog 2024-05-13 07:57:58 +08:00
Steven eda1983964 chore: return workspace setting with default value 2024-05-12 13:32:26 +08:00
Steven cf423026a5 chore: update store cache 2024-05-12 13:19:31 +08:00
Leo LI 93e8fa4912 fix: upgrade scripts for mysql
* Fix mysql db migration

* Update store/db/mysql/migration/prod/0.22/01__memo_tags.sql

* Update store/db/mysql/migration/prod/0.22/02__memo_payload.sql

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-05-12 12:34:21 +08:00
Steven bb076ce486 chore: update list workspace settings 2024-05-12 08:09:14 +08:00
Steven cf7718f8dc chore: update presign expires 2024-05-12 08:03:56 +08:00
Steven 29a22914cf fix: postgres upgrade script 2024-05-11 22:35:26 +08:00
Steven 087f60ba7b chore: fix user setting key checks 2024-05-11 21:14:21 +08:00
wzc90 d4157bcffa fix: upgrade scripts (#3347) 2024-05-11 17:43:13 +08:00
Michael ee984a8872 chore: translated using Weblate (Chinese (Simplified)) (#3345)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Coisini-H <2972186196@qq.com>
2024-05-11 16:00:33 +08:00
wzc90 80df8f8aed fix: upgrade scripts (#3344) 2024-05-11 15:38:14 +08:00
Michael a15025303b chore: update i18n with Weblate (#3339)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 99.6% (254 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-05-11 08:15:40 +08:00
Lincoln Nogueira f45f673aec chore: respect supplied listening address (#3338) 2024-05-11 06:50:22 +08:00
Steven f30599fbd2 chore: fix scripts 2024-05-10 23:23:15 +08:00
Steven 041f9b1beb chore: bump version 2024-05-10 23:02:57 +08:00
boojack 3fbc4d8539 feat: implement drag and drop for resource order in editor (#3337)
* Implement drag and drop for resource order in editor

* chore: update

* chore: update

* chore: update
2024-05-10 20:34:35 +08:00
Steven 5f207c8f0c fix: math overflow 2024-05-10 06:21:47 +08:00
Michael fe5a0fe98a chore: update i18n with Weblate (#3335)
* Translated using Weblate (Japanese)

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (255 of 255 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-09 22:40:27 +08:00
Steven 584c669068 chore: tweak max width 2024-05-09 22:10:27 +08:00
Steven 46a085f8df chore: add datepicker to timeline 2024-05-09 20:31:37 +08:00
Steven e7a788fa71 chore: tweak memo detail page 2024-05-09 20:10:13 +08:00
Steven 942052b1ea chore: update grpc options 2024-05-09 20:08:18 +08:00
Steven deae53c1f1 chore: add dayjs to fix datetime format in safari 2024-05-09 08:52:34 +08:00
Steven 1d99dad435 feat: update timeline page 2024-05-09 07:56:00 +08:00
Steven 33133ea1a3 chore: tweak searchbar styles 2024-05-08 22:50:13 +08:00
Steven a4235bb4bf chore: tweak tags style 2024-05-08 22:31:22 +08:00
Steven e0977e53f7 chore: remove unused route 2024-05-08 22:15:29 +08:00
Michael 4e12744811 chore: update translation files (#3332)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-08 21:35:19 +08:00
Steven 40a5503d45 chore: tweak i18n locales 2024-05-08 21:33:49 +08:00
Steven 16670b6b8d chore: tweak seed data 2024-05-08 20:08:53 +08:00
Michael d57e7d5a0b chore: update translation files (#3331)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-05-08 20:06:05 +08:00
Steven f7f4206fa1 chore: fix linter 2024-05-08 20:05:16 +08:00
Steven 292861be16 chore: retire tag store 2024-05-08 20:03:18 +08:00
Steven d0655ece53 refactor: update memo tags 2024-05-08 20:03:01 +08:00
Steven 2c270438ec chore: update default service config 2024-05-08 06:57:53 +08:00
Jerwin Arnado a9caecf479 fix: Set max height to 50vh for better viewing for larger screens. (#3330)
Feature: Set max height to 50vh for better viewing for larger screens.
2024-05-07 23:19:20 +08:00
Steven d355e2c631 chore: tweak tags section 2024-05-07 22:11:46 +08:00
Steven 4950ea1c74 fix: grpc max message size 2024-05-07 22:10:27 +08:00
Steven f9258e41a0 chore: tweak max width 2024-05-07 22:10:08 +08:00
steven e16546f80a chore: handle legacy workspace setting 2024-05-07 22:07:44 +08:00
dependabot[bot] a73f979f96 chore: bump lucide-react from 0.368.0 to 0.378.0 in /web (#3313)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.368.0 to 0.378.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.378.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:35 +08:00
dependabot[bot] 41549a6951 chore: bump @types/node from 20.12.9 to 20.12.10 in /web (#3323)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.9 to 20.12.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:18 +08:00
dependabot[bot] 1e8346290c chore: bump @mui/joy from 5.0.0-beta.32 to 5.0.0-beta.36 in /web (#3317)
Bumps [@mui/joy](https://github.com/mui/material-ui/tree/HEAD/packages/mui-joy) from 5.0.0-beta.32 to 5.0.0-beta.36.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/HEAD/packages/mui-joy)

---
updated-dependencies:
- dependency-name: "@mui/joy"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 08:53:06 +08:00
dependabot[bot] 6a2701ee83 chore: bump react-redux from 9.1.1 to 9.1.2 in /web (#3316) 2024-05-07 05:11:26 +08:00
dependabot[bot] 68fcf250a0 chore: bump google.golang.org/protobuf from 1.33.0 to 1.34.1 (#3318) 2024-05-07 05:11:15 +08:00
dependabot[bot] 5aaf0b88fd chore: bump golang.org/x/oauth2 from 0.19.0 to 0.20.0 (#3319) 2024-05-07 05:11:04 +08:00
dependabot[bot] f9b0a2b693 chore: bump golang.org/x/crypto from 0.22.0 to 0.23.0 (#3320) 2024-05-07 05:10:52 +08:00
dependabot[bot] bf07a2cfe6 chore: bump modernc.org/sqlite from 1.29.8 to 1.29.9 (#3321) 2024-05-07 05:10:40 +08:00
Steven 776664105a chore: tweak content length limit 2024-05-06 19:12:30 +08:00
Michael b0ecb72eaa chore: translated using Weblate (Hungarian) (#3312)
Translated using Weblate (Hungarian)

Currently translated at 98.6% (299 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

Co-authored-by: Vermunds <33235701+Vermunds@users.noreply.github.com>
2024-05-06 08:03:52 +08:00
Steven af1ad2f2db chore: add memo content length limit setting 2024-05-06 08:02:39 +08:00
Nabiel Omar Syarif 56ceba2dec fix: fix deleting tag from tag lists (#3311) 2024-05-06 07:38:15 +08:00
Steven e32a585bbf chore: update resource dashboard 2024-05-06 07:37:48 +08:00
Steven dfc0889a4f chore: tweak package name 2024-05-06 07:18:54 +08:00
Michael da535c8dc6 chore: translated using Weblate (Chinese (Simplified)) (#3307)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Sung Kim <1740603900@qq.com>
2024-05-04 11:52:26 +08:00
Steven 10c57167cc chore: remove unused flags 2024-05-03 07:16:07 +08:00
Steven 5742f9ca13 fix: seed data 2024-05-03 07:02:08 +08:00
Steven e9831caca1 chore: remove unused field 2024-05-02 22:21:49 +08:00
Steven b23b6302de chore: tweak linter 2024-05-02 22:10:50 +08:00
Steven 74145157a0 chore: add presign background service 2024-05-02 22:08:45 +08:00
Steven 05f73a2236 chore: tweak linter 2024-05-02 21:46:47 +08:00
Steven 775b79338d chore: update object in s3 2024-05-02 21:44:17 +08:00
Steven 26545c855c refactor: implement s3 storage 2024-05-02 21:28:06 +08:00
Michael 355ea352aa chore: translated using Weblate (Chinese (Traditional)) (#3304)
Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (303 of 303 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (303 of 303 strings)


Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/
Translation: memos-i18n/i18n

Co-authored-by: Yuri <isyuricunha@duck.com>
2024-05-02 20:23:12 +08:00
Steven 144269fbbc chore: fix router 2024-05-01 12:44:18 +08:00
Steven 590b626052 chore: update upload resources button 2024-05-01 10:43:09 +08:00
Steven 832ad92bac chore: update gitignore 2024-05-01 10:31:26 +08:00
Steven 20dd3e17f7 chore: rename router package 2024-05-01 10:28:32 +08:00
Steven 8ae4bc95dc chore: migrate auth package 2024-05-01 10:26:46 +08:00
Steven ff175bbb7e refactor: update resource binary request handler 2024-05-01 10:23:56 +08:00
Steven 6d3d71df30 chore: update frontend dependencies 2024-04-30 22:27:20 +08:00
Steven d668794c7c chore: update build docker image actions 2024-04-30 22:21:46 +08:00
Steven 33f52320f7 fix: remove lazy import components 2024-04-30 22:06:47 +08:00
Steven 6295979592 chore: add user avatar route 2024-04-30 22:06:34 +08:00
Michael cac6f42770 fix: server matchs 2024-04-30 10:18:04 +08:00
dependabot[bot] 00f1773495 chore: bump golangci/golangci-lint-action from 4 to 5 (#3298)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-29 23:28:15 +08:00
Steven 8a3845ff54 chore: remove external resource dialog 2024-04-29 22:57:47 +08:00
Steven 155c5baf2c refactor: add markdown service 2024-04-29 08:00:37 +08:00
Steven 4338234641 chore: retire storage related functions 2024-04-28 21:50:09 +08:00
Steven 320963098f refactor: update storage setting 2024-04-28 21:36:22 +08:00
Steven f25c7d9b24 fix: serve frontend assets 2024-04-28 08:36:33 +08:00
Steven d8aeec993c chore: replace classnames with clsx 2024-04-28 00:58:40 +08:00
Steven 1b291422e7 refactor: api version 2024-04-28 00:44:29 +08:00
Steven 8bba7f706e chore: update IME mode checks 2024-04-28 00:12:44 +08:00
Steven f9942002f9 chore: fix linter 2024-04-27 23:36:57 +08:00
Steven 92872118b9 refactor: tweak api definition 2024-04-27 23:14:58 +08:00
Steven 9b66ef5e26 chore: tweak api definition 2024-04-27 22:02:15 +08:00
Steven 04c78e180c chore: update buf dependencies 2024-04-27 00:37:45 +08:00
Michael cc2370e01e chore: update i18n with Weblate (#3287)
* Translated using Weblate (Japanese)

Currently translated at 91.0% (276 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: mirukupc <mirukupc.jp@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-27 00:32:58 +08:00
Steven 7217605831 chore: update gitignore 2024-04-27 00:26:04 +08:00
Steven a6a62eb79c chore: update gitignore 2024-04-27 00:25:47 +08:00
Steven 5f26c52b49 feat: add goreleaser 2024-04-27 00:22:27 +08:00
Steven 647602beac chore: update link preview 2024-04-25 21:01:13 +08:00
Steven 81d24f32a7 fix: memo comment keys 2024-04-25 09:10:11 +08:00
SkyWT 9bcd4f59a2 fix: editor IME composing event behavior (#3267)
* fix: editor IME composing event behavior

* fix: editor IME composing event behavior

* Update web/src/components/MemoEditor/hooks/useAutoComplete.ts

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-04-25 08:59:26 +08:00
Steven 205bf7ed0e chore: update link target 2024-04-24 22:02:11 +08:00
Steven cdcb61da17 chore: fix update storage 2024-04-24 09:18:33 +08:00
Michael 7f9af9b12c chore: translated using Weblate (French) (#3272)
Translated using Weblate (French)

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Alexis <alexisl61@outlook.fr>
2024-04-24 06:22:57 +08:00
dependabot[bot] 6b253247cb chore: bump modernc.org/sqlite from 1.29.7 to 1.29.8 (#3266)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.7 to 1.29.8.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.7...v1.29.8)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 10:04:10 +08:00
Michael 761b4e115b chore: translated using Weblate (English) (#3259)
Translated using Weblate (English)

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

Co-authored-by: noxonad <noxonad@proton.me>
2024-04-22 10:11:30 +08:00
Nabiel Omar Syarif 16f209eada fix: specify go toolchain in go.mod (fix #3252) (#3253) 2024-04-22 10:06:33 +08:00
刘明野 06a79a2e37 fix: tag dependencies (#3251)
fix: 修改tag名称后重新请求数据
2024-04-20 21:16:17 +08:00
Michael 330cc3dc89 chore: translated using Weblate (French) (#3249)
Translated using Weblate (French)

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Alexis <alexisl61@outlook.fr>
2024-04-19 08:58:39 +08:00
Steven e8dfd579c3 chore: update background services 2024-04-18 23:34:35 +08:00
Steven 2a93b8d720 chore: tweak linter 2024-04-18 21:44:46 +08:00
Steven 5d967f41d9 chore: update server 2024-04-18 21:41:00 +08:00
Steven 339fecbfff chore: allow search comments 2024-04-18 21:04:10 +08:00
Steven 2cdcd17ba3 chore: tweak linter 2024-04-17 09:00:16 +08:00
Steven 14d4cfd5a4 chore: tweak store methods name 2024-04-17 08:56:52 +08:00
Michael 00d25b12c1 chore: translated using Weblate (Russian) (#3245)
Translated using Weblate (Russian)

Currently translated at 90.4% (274 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

Co-authored-by: sergeybutakov <pushkagun@gmail.com>
2024-04-16 22:38:20 +08:00
Steven 95df647265 chore: tweak comments 2024-04-16 22:33:25 +08:00
Steven f52e0e005a chore: update dependencies 2024-04-16 21:28:40 +08:00
Steven 70f3d131f6 chore: update pnpm version 2024-04-16 21:22:40 +08:00
Steven f7f139d65a chore: tweak typo 2024-04-16 21:15:17 +08:00
coderwander 162521885c chore: fix some typos in comments (#3243)
Signed-off-by: coderwander <770732124@qq.com>
2024-04-16 21:14:38 +08:00
dependabot[bot] b0b9513de7 chore: bump @types/react from 18.2.75 to 18.2.79 in /web (#3240)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.75 to 18.2.79.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:36:03 +08:00
dependabot[bot] f221f9bfe9 chore: bump i18next from 23.11.1 to 23.11.2 in /web (#3235)
Bumps [i18next](https://github.com/i18next/i18next) from 23.11.1 to 23.11.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.11.1...v23.11.2)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:40 +08:00
dependabot[bot] e831fa8190 chore: bump react-redux from 9.1.0 to 9.1.1 in /web (#3234)
Bumps [react-redux](https://github.com/reduxjs/react-redux) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/reduxjs/react-redux/releases)
- [Changelog](https://github.com/reduxjs/react-redux/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reduxjs/react-redux/compare/v9.1.0...v9.1.1)

---
updated-dependencies:
- dependency-name: react-redux
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:23 +08:00
dependabot[bot] eae0b7115b chore: bump @types/react-dom from 18.2.24 to 18.2.25 in /web (#3233)
Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 18.2.24 to 18.2.25.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:08:01 +08:00
dependabot[bot] 1f0fffda95 chore: bump lucide-react from 0.367.0 to 0.368.0 in /web (#3232)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.367.0 to 0.368.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.368.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 07:07:49 +08:00
Michael 404751f378 chore: update i18n with Weblate (#3230)
* Translated using Weblate (Turkish)

Currently translated at 100.0% (303 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (302 of 303 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-15 11:19:52 +08:00
Steven f9dd29ae07 chore: tweak tag store 2024-04-14 22:20:09 +08:00
Steven 1f0bfd2169 chore: update tag store 2024-04-14 22:03:56 +08:00
Michael 4aa72306ff chore: update i18n with Weblate (#3227)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (308 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (307 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-04-14 21:27:55 +08:00
Eng Zer Jun 3b550a8ab8 chore: replace util.Min helper with built-in min (#3224) 2024-04-13 20:16:22 +08:00
Steven cb7886dc49 chore: retire telegram integration in frontend 2024-04-13 12:42:34 +08:00
Steven d00e4fdf17 chore: retire telegram plugin 2024-04-13 12:39:41 +08:00
Steven 9a2c423435 chore: update var-naming 2024-04-13 12:11:59 +08:00
Steven 49f8cfd5d1 chore: update jwt middleware 2024-04-13 12:10:57 +08:00
Steven b27004daae chore: retire unused plugin 2024-04-13 12:09:32 +08:00
Steven 75359854cc chore: fix resource routes 2024-04-13 12:07:53 +08:00
Steven cebc46adc7 chore: tweak store definition 2024-04-13 11:54:37 +08:00
Steven 6ee3b0f704 chore: go mod tidy 2024-04-13 11:02:29 +08:00
Steven bbd206e893 chore: retire legacy api 2024-04-13 11:01:16 +08:00
Steven cf4db17080 chore: fix linter 2024-04-13 10:53:39 +08:00
Steven c373131b89 chore: migrate idp service 2024-04-13 10:50:25 +08:00
Steven a77703260f chore: fix linter 2024-04-13 02:57:32 +08:00
Steven 8f51529c78 chore: implement storage service 2024-04-13 02:55:40 +08:00
Steven 707e5caf89 chore: update workspace setting store 2024-04-13 02:08:35 +08:00
Michael 17e8fc5408 chore: update i18n with Weblate (#3220)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 98.0% (302 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 98.0% (302 of 308 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
2024-04-12 22:45:12 +08:00
Steven 074e7cf71a chore: fix resource path 2024-04-12 08:57:34 +08:00
Steven f5461264c5 chore: fix dialog background color 2024-04-12 08:44:19 +08:00
Michael e2ae32063e chore: translated using Weblate (Turkish) (#3215)
Translated using Weblate (Turkish)

Currently translated at 100.0% (300 of 300 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-04-12 08:36:38 +08:00
Steven 133951328b chore: fix linter 2024-04-12 08:36:02 +08:00
imikod 257b8add8c chore: localization improvements (#3213)
* localization improvements

* typo fix

* fix linting error
2024-04-12 08:35:14 +08:00
Steven 755d5b83c6 chore: retire legacy setting api 2024-04-12 08:32:54 +08:00
Steven 3088cabe10 chore: tweak linter 2024-04-11 17:58:49 +08:00
Steven 3e6e56b008 refactor: update workspace store definition 2024-04-11 17:53:00 +08:00
Steven 6d842711e2 chore: fix dependencies 2024-04-10 23:34:29 +08:00
dependabot[bot] b84a0592bb chore: bump react-i18next from 11.18.6 to 14.1.0 in /web (#3210)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 11.18.6 to 14.1.0.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v11.18.6...v14.1.0)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:28:11 +08:00
dependabot[bot] 581a64d5c1 chore: bump lucide-react from 0.309.0 to 0.367.0 in /web (#3208)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.309.0 to 0.367.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.367.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:27:34 +08:00
dependabot[bot] 4537411109 chore: bump @typescript-eslint/eslint-plugin from 6.21.0 to 7.0.0 in /web (#3207)
chore: bump @typescript-eslint/eslint-plugin in /web

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.21.0 to 7.0.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.0.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:53 +08:00
dependabot[bot] d6b1326a2d chore: bump eslint-config-prettier from 8.10.0 to 9.1.0 in /web (#3206)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.10.0 to 9.1.0.
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.10.0...v9.1.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:36 +08:00
dependabot[bot] 9490e890c7 chore: bump i18next from 21.10.0 to 23.11.1 in /web (#3205)
Bumps [i18next](https://github.com/i18next/i18next) from 21.10.0 to 23.11.1.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v21.10.0...v23.11.1)

---
updated-dependencies:
- dependency-name: i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:22 +08:00
dependabot[bot] aed76165ea chore: bump @reduxjs/toolkit from 1.9.7 to 2.2.3 in /web (#3204)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 1.9.7 to 2.2.3.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v1.9.7...v2.2.3)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:26:11 +08:00
dependabot[bot] 51a90b0013 chore: bump golangci/golangci-lint-action from 3 to 4 (#3203)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3 to 4.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:25:53 +08:00
dependabot[bot] 7b1fe9fcfc chore: bump pnpm/action-setup from 2.4.0 to 3.0.0 (#3202)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2.4.0 to 3.0.0.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2.4.0...v3.0.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:25:42 +08:00
Steven ec67f1b3c9 chore: add dependabot 2024-04-10 23:24:17 +08:00
Steven 97cfab1758 chore: upgrade dependencies 2024-04-10 23:19:59 +08:00
Steven eb251a097e chore: update workspace setting service 2024-04-10 23:01:01 +08:00
Steven 4c47e93fce chore: tweak workspace setting store 2024-04-10 22:31:55 +08:00
Michael af954db473 chore: update i18n with Weblate (#3201)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (299 of 299 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
2024-04-10 22:05:31 +08:00
Steven a376dc4dd6 chore: fix linter 2024-04-10 22:04:02 +08:00
Dubzer 8ee56bd29f feat: add code wrapping option on mobile devices (#3196)
* feat: add code wrapping option on mobile devices

* Minor changes

* oopsie
2024-04-10 22:03:47 +08:00
Steven 71c39ed554 chore: update workspace setting definition 2024-04-10 21:15:55 +08:00
Steven c93b1efbae chore: update workspace setting store 2024-04-10 20:05:17 +08:00
Steven 58ae3217ff chore: update auth callback messages 2024-04-09 21:23:17 +08:00
Steven 6028838f03 chore: update component name 2024-04-09 20:51:09 +08:00
Michael 000b3a7a2c chore: update i18n with weblate (#3195)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-04-09 20:29:26 +08:00
Steven bbdd40b2b0 chore: add placeholder to comment editor 2024-04-09 20:01:19 +08:00
imikod 8356ebc46b chore: improve localization (#3190)
* improve localization

* follow suggestion
2024-04-09 16:11:32 +08:00
Steven fc95876617 chore: update memo creator display 2024-04-09 09:05:34 +08:00
Steven b1e196bb4f fix: delete memo reaction 2024-04-08 20:52:46 +08:00
Steven 6d10251cbd feat: impl list syntax auto complete to editor 2024-04-08 20:42:53 +08:00
Steven 436a6cb084 chore: fix text truncate 2024-04-08 19:20:16 +08:00
imikod 90ed908d2e fix: set navigation icons to not shrink (#3186) 2024-04-08 10:16:52 +08:00
Steven 756ab71302 chore: tweak truncate styles 2024-04-07 23:30:28 +08:00
Steven a6b09aa5b1 chore: add confirm dialog for disable password login setting 2024-04-07 23:22:59 +08:00
Steven ff81ea602d chore: tweak error message 2024-04-07 22:35:02 +08:00
Steven 8101a5e0b1 chore: add origin flag to config cors 2024-04-07 22:15:15 +08:00
Michael b5893aa60b chore: update i18n with Weblate (#3183)
* Translated using Weblate (French)

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/tr/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: Oğuz Han <h4n.3545@gmail.com>
2024-04-07 10:13:12 +08:00
Steven bedf3b3025 chore: tweak embedded memo styles 2024-04-02 23:32:43 +08:00
The Anh Nguyen 09ffa7b818 chore: fix memo link (#3173) 2024-04-02 07:13:58 +08:00
Steven ba7dbc1fca chore: fix task node click handler 2024-04-01 21:38:18 +08:00
Steven 15ef57589e chore: go mod tidy 2024-04-01 21:35:58 +08:00
stayweek 5aa633948e chore: use the built-in slices library (#3172)
Signed-off-by: stayweek <jiangtengtao@outlook.com>
2024-04-01 17:16:29 +08:00
Steven b1297f5d01 chore: tweak linter 2024-04-01 00:41:25 +08:00
Steven 33e9b13665 chore: tweak linter 2024-04-01 00:34:51 +08:00
Steven b79f626a74 chore: fix memo comment inbox 2024-04-01 00:26:46 +08:00
Michael ec35a42fb5 chore: update i18n with Weblate (#3168)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (295 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (290 of 295 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-04-01 00:07:03 +08:00
Michael 98c9ab70e2 chore: update translation files (#3166)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-30 22:54:38 +08:00
Steven edc7645086 chore: fix linter 2024-03-30 15:01:19 +08:00
Steven cbebbca7d6 chore: add idp definition 2024-03-30 14:58:47 +08:00
Steven 4d62ed46cc chore: tweak words 2024-03-30 14:14:42 +08:00
Steven bb10bb200c chore: implement search random memos 2024-03-30 13:50:18 +08:00
Steven 03c93785f4 chore: implement list random users 2024-03-30 13:29:48 +08:00
The Anh Nguyen 2fe6d606ec feat: handle restore memo when is in archived memo detail page (#3165) 2024-03-30 13:06:08 +08:00
Steven c8baeb86ec chore: fix memo links 2024-03-30 13:04:40 +08:00
The Anh Nguyen 9a88e00df0 fix: link embedded content to uid instead of name (#3164) 2024-03-30 12:30:09 +08:00
Steven 54a3c25ebd chore: update memo resource name definition 2024-03-30 08:26:28 +08:00
Steven d84a88e805 chore: fix linter 2024-03-30 00:05:19 +08:00
Steven 5ab845d92e chore: fix linter 2024-03-30 00:02:34 +08:00
Steven 4f7a6cd6cc chore: fix default logo url 2024-03-29 23:12:30 +08:00
Steven c7aaf791e6 chore: tweak props naming 2024-03-29 22:49:19 +08:00
Michael 239348c403 chore: update i18n with Weblate (#3162)
* Translated using Weblate (Russian)

Currently translated at 85.1% (252 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

* Translated using Weblate (Vietnamese)

Currently translated at 91.8% (272 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/vi/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: The Anh Nguyen <anhntdev0@gmail.com>
2024-03-29 21:32:55 +08:00
Michael 9f803aa9bb chore: translated using Weblate (Russian) (#3161)
Translated using Weblate (Russian)

Currently translated at 85.1% (252 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

Co-authored-by: xyznetsov <invisiblesun2016@yandex.ru>
2024-03-29 21:29:49 +08:00
Steven 200a0d3e2b fix: memo relations 2024-03-29 21:27:38 +08:00
Steven ea6628066d chore: update sidebar components 2024-03-29 09:16:55 +08:00
Steven 526f46807e chore: tweak user list display 2024-03-29 08:37:07 +08:00
Michael bfaf06582c chore: translated using Weblate (Portuguese (Brazil)) (#3157)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (296 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-29 08:20:56 +08:00
Steven 7331c598df fix: edit account dialog fields 2024-03-29 08:19:32 +08:00
The Anh Nguyen f7a445ac8b chore: update Vietnamese translation (#3155) 2024-03-29 08:07:02 +08:00
Steven 90679cc33a chore: add explore sidebar 2024-03-29 00:01:45 +08:00
Steven 192ee7acc0 chore: fix memo link 2024-03-28 22:53:22 +08:00
Michael 7d94256a2a chore: update i18n with Weblate (#3152)
* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: Coisini-H <2972186196@qq.com>
2024-03-28 22:51:50 +08:00
Michael aed4c1392d chore: update i18n with Weblate (#3151)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (296 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 98.3% (291 of 296 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
2024-03-28 22:48:32 +08:00
Paul 3605efc4d1 chore: removed sanitization logic (#3147)
* removed sanitization logic

* to avoid lint err
2024-03-28 22:44:44 +08:00
Dubzer a0846c2818 feat: add shortcut to edit the previous memo (#3122)
* Add shortcut to edit the previous memo

* Fix compilation

* Update web/src/components/MemoEditor/index.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-03-27 21:46:29 +08:00
Steven 2ebea4dba9 chore: fix workspace profile api 2024-03-27 18:51:11 +08:00
Steven 16cfef32d6 chore: tweak statistics translation 2024-03-26 23:49:37 +08:00
Steven f637deacfc chore: tweak tag list 2024-03-26 23:43:31 +08:00
Steven a07805907b chore: fix action run 2024-03-26 22:46:17 +08:00
Steven 2e87da4927 chore: update frontend dependencies 2024-03-26 22:35:11 +08:00
Steven d460e6bf41 fix: link node 2024-03-25 23:59:19 +08:00
Steven e703b4f70d fix: resource v1 definition 2024-03-24 22:35:10 +08:00
Steven be525fa3df chore: fix migration script 2024-03-23 01:03:11 +08:00
Steven d1e8af48c0 chore: tweak memo view styles 2024-03-23 00:58:15 +08:00
Steven 005305cd9a chore: update relative time display 2024-03-22 08:12:08 +08:00
Steven 8fd1dff484 chore: update migration scripts 2024-03-21 22:24:39 +08:00
Steven c5fa4fe304 chore: tweak imports order 2024-03-21 21:44:43 +08:00
Steven 8f37d7490c chore: fix linter 2024-03-21 21:42:44 +08:00
Steven 18d16abdb5 chore: update workspace service 2024-03-21 21:39:34 +08:00
Steven 1d83c68cb5 chore: update type definitions 2024-03-21 08:12:38 +08:00
Michael 861a1e4c9b chore: update i18n with Weblate (#3115)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Coisini-H <2972186196@qq.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
2024-03-20 21:42:08 +08:00
Steven 26e5b70483 chore: upgrade frontend dependencies 2024-03-20 21:32:06 +08:00
Steven 7c5261b5d2 chore: tweak resource definition 2024-03-20 21:17:04 +08:00
Steven 7cc8b951a3 refactor: update resource id naming 2024-03-20 20:39:16 +08:00
Steven a3a4e37cb0 chore: update memo content styles 2024-03-20 09:07:54 +08:00
Steven 76c936357b chore: fix resource link 2024-03-20 08:51:32 +08:00
Steven 6db427e396 chore: update acl list 2024-03-20 08:18:43 +08:00
Steven 0a0ccbf6e1 chore: update acl list 2024-03-20 08:12:46 +08:00
Steven 96a7d0eb25 chore: tweak line height 2024-03-20 00:40:46 +08:00
Steven ed89cb8310 chore: update memo relation definition 2024-03-19 21:53:44 +08:00
Steven 722e356044 chore: update memo store 2024-03-19 20:55:33 +08:00
Steven efb15a0453 chore: tweak naming 2024-03-18 23:41:57 +08:00
Steven 5f2d6b22be chore: tweak memo structure 2024-03-18 23:23:53 +08:00
Steven 2dc8ed773c chore: tweak linter 2024-03-18 19:57:53 +08:00
Steven 86db6d0254 chore: tweak user api definition 2024-03-18 12:56:52 +08:00
Steven f3fb5e0c60 chore: tweak route enum 2024-03-18 12:07:44 +08:00
Steven 1e43c8d84b chore: disallow update workspace setting in demo mode 2024-03-17 19:18:45 +08:00
Steven cf207df672 chore: tweak link styles 2024-03-17 18:28:37 +08:00
Michael 5dd1251d1e chore: update i18n with Weblate (#3109)
* Translated using Weblate (Japanese)

Currently translated at 95.2% (279 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Somme4096 <somme4096@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-17 18:22:22 +08:00
sunxunle ea104a5e54 chore: fix typo (#3106) 2024-03-17 09:52:04 +08:00
Steven 335a0312f2 chore: tweak link styles 2024-03-16 23:35:36 +08:00
Mehad Nadeem 9c1e2f8137 feat: implemented link previews (frontend files) (#3074)
* feat: implmented link previews (frontend files)

* chore: updated frontend side for Link Previews

* chore: updated frontend gen types with the renamed (server) service file

* fix: passing errors

* chore: switched to using generated type instead of separate fields

* fix: passing linter error

* chore: updated Link.tsx

* chore: using `useResponsiveWidth` to render for different devices

* chore: refactored Link.tsx
2024-03-16 22:51:16 +08:00
Steven 14479347d8 chore: remove demo checks 2024-03-15 09:05:02 +08:00
Steven 0f48cfbb4e chore: tweak padding styles 2024-03-15 08:52:11 +08:00
Steven 606a30640d fix: check username in signup 2024-03-15 08:37:58 +08:00
Steven ab136e3310 chore: tweak styles 2024-03-15 00:12:22 +08:00
Michael 21af2a004d chore: translated using Weblate (French) (#3099)
Translated using Weblate (French)

Currently translated at 100.0% (293 of 293 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

Co-authored-by: Ezmana <ezmana.land@gmail.com>
2024-03-14 17:09:29 +08:00
Steven 115b5551b3 chore: tweak default avatar 2024-03-14 09:11:57 +08:00
Steven 15be18fa85 chore: update compace mode handler 2024-03-14 09:07:18 +08:00
Steven 9ce381abb9 chore: tweak user profile 2024-03-14 00:13:56 +08:00
Steven 2516431b20 chore: tweak memo content styles 2024-03-14 00:01:33 +08:00
Steven ded4da07a3 feat: use @github/relative-time-element to display time 2024-03-13 23:47:34 +08:00
Steven e795149186 chore: tweak memo view display 2024-03-13 22:30:59 +08:00
Steven 8fe6874b1b chore: add description field to user 2024-03-13 21:24:16 +08:00
boojack 7c1510e7a9 chore: update i18n with Weblate (#3090)
* Translated using Weblate (Spanish)

Currently translated at 95.4% (293 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/es/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Hisiste <aditooliva@gmail.com>
Co-authored-by: keocheung <keocheung@outlook.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-13 20:55:04 +08:00
Steven e5fc107920 chore: tweak i18n locales 2024-03-13 20:51:19 +08:00
Steven 5d740c3813 chore: update link service 2024-03-13 20:25:27 +08:00
Mehad Nadeem 0abe20df72 feat: implemented link previews (server files) (#3073)
* feat: implmented link previews (server files)

* chore: updated variable name

* chore: renamed service file from `metadata_service.go` to `link_service.go`

* fix: passing errors

* fix: fixed linter warnong about `ctx`
2024-03-13 17:31:53 +08:00
Mehad Nadeem 4d41b68d4c feat: implemented link previews (proto files) (#3072)
* feat: implmented link previews (proto files)

* fix: passing proto linter errors

* chore: renamed MetadataService service in proto file.

* fix: removed unused files

* chore: removed meaningless comments from proto file
2024-03-13 16:52:59 +08:00
Lincoln Nogueira 7c87c1ff74 chore: update build scripts (#3085) 2024-03-13 08:50:56 +08:00
Steven 963c630428 chore: update readme with weblate 2024-03-13 08:25:38 +08:00
Steven 6b6edc3791 chore: update tg message handler 2024-03-12 22:48:53 +08:00
Mario Gómez 425e85f0f9 chore: fix spanish typos (#3083) 2024-03-12 21:48:02 +08:00
huajin tong 8e7f826ae6 chore: fix typo (#3080)
Signed-off-by: thirdkeyword <fliterdashen@gmail.com>
2024-03-12 17:05:49 +08:00
Michael 9ffc1515f4 chore: update i18n with Weblate (#3079)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Matsuri <matsuri@vmoe.info>
Co-authored-by: keocheung <keocheung@outlook.com>
2024-03-12 13:14:56 +08:00
steven 8cdc0c7ffa chore: add delete tag action 2024-03-09 17:26:58 +08:00
zty 999a05307e fix: body overflow styles #3056
Co-authored-by: zty <zty.dev@outlook.com>
2024-03-09 14:09:31 +08:00
steven ed1954c58c chore: fix check setting value 2024-03-09 12:56:44 +08:00
steven 77bafba682 chore: update gomark.wasm 2024-03-09 12:47:20 +08:00
Michael 1540de2f44 chore: translated using Weblate (Korean) (#3060)
Translated using Weblate (Korean)

Currently translated at 95.1% (292 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

Co-authored-by: WonSeok <wonseok@duck.com>
2024-03-09 12:40:42 +08:00
Steven ed4b48c54f chore: update gomark.wasm 2024-03-08 00:34:34 +08:00
Michael 706e749275 chore: translated using Weblate (Portuguese (Brazil)) (#3050)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (307 of 307 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2024-03-07 11:38:24 +08:00
Steven 845999292a chore: update frontend dependencies 2024-03-06 23:33:00 +08:00
Michael 240da335c1 chore(i18n): update translation files (#3042)
Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

Co-authored-by: Hosted Weblate <hosted@weblate.org>
2024-03-05 11:44:51 +08:00
Steven f9f277695d chore: fix comment amount 2024-03-04 23:37:38 +08:00
Dubzer 6cbfbe9c07 chore: settings page improvements (#3034)
* Don't allow to select text on buttons in settings + refactoring

* Remove redundant useMemo

* Update web/src/pages/Setting.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Rename other constants too

* Rename AdminSection to ADMIN_SECTIONS

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-03-04 23:33:43 +08:00
Steven ec206104e5 chore: tweak i18n locale 2024-03-04 23:23:14 +08:00
Steven 342f341b3d chore: ignore import locale error 2024-03-04 13:16:55 +08:00
WonSeok f46b64a17d fix: check disallow public memo in Telegram(#3036) (#3037) 2024-03-04 11:24:09 +08:00
Steven 7d5f603482 chore: update compact view 2024-03-04 11:21:48 +08:00
Dubzer f0a521f5b8 feat: improve theming (#3032)
Add color-scheme and dark scrollbar styles
2024-03-04 09:35:40 +08:00
Steven 59314cdf80 chore: add compact mode to memo view 2024-03-04 01:11:34 +08:00
Steven ac0315334d chore: update i18n locales imports 2024-03-04 00:05:27 +08:00
Steven ac8a374ebd chore: bump version 2024-03-03 23:45:52 +08:00
Steven 95b02341eb chore: tweak logger 2024-03-03 23:45:32 +08:00
Steven d34273b186 chore: update memo icons style 2024-03-03 16:41:03 +08:00
Steven dcfb2b7de2 chore: tweak docs generate path 2024-03-03 15:05:42 +08:00
Steven ebcf43c997 chore: update gomark.wasm 2024-03-03 14:56:40 +08:00
Steven cfb50f19aa chore: tweak linter 2024-03-03 14:23:21 +08:00
Steven e441e3882b chore: update error logger 2024-03-03 14:20:59 +08:00
Steven c1da87a819 chore: update get request origin 2024-03-03 14:10:48 +08:00
jjaychen 3b089eeae3 fix: ignore "Tab" key down event when is composing in editor(#3026) (#3027) 2024-03-03 13:04:00 +08:00
Steven 9a8a1d017e chore: add comments icon 2024-03-02 11:29:21 +08:00
Steven 7e23ceb242 chore: fix frontend linter 2024-03-01 19:39:24 +08:00
Steven 898b3c3779 chore: update gomark.wasm 2024-03-01 19:31:00 +08:00
Steven 8eb01adb6f chore: go mod tidy 2024-02-29 23:56:20 +08:00
jg0312 621a8d4e20 chore: fix typo in build script's if statement (#3017)
missing 'i' in 'if' statement
2024-02-29 23:55:25 +08:00
Steven dfa78cac49 chore: update logger 2024-02-29 23:54:43 +08:00
Steven 12f4d3a10d chore: tweak default page size 2024-02-29 23:42:06 +08:00
Steven 00788bd8f8 chore: update actions 2024-02-29 09:21:55 +08:00
Steven 5f2a624c0c chore: tweak imports order 2024-02-29 01:32:59 +08:00
Steven 3e50bee7da chore: move api directory 2024-02-29 01:16:43 +08:00
Steven 1aa75847d6 chore: upgrade gomark 2024-02-29 01:07:53 +08:00
Steven 89a270cede chore: add username to cache key 2024-02-28 00:34:55 +08:00
Xylit 5526355621 fix: dark mode tag selection and suggestion (#3004)
* fix: use correct higlight color on selecting a tag in darkmode

* fix: take scrolling into account in tab suggestion

Issue: When editing a long memo and editing a tag somewhere where the user has
to scroll down to, the tag suggestions would be out of place (too far down)
because the scrolling wouldn't be taken into account.

Fix: Substract the suggestions div by the scroll amount.

* fix: don't show tag suggestion when on '#'

Fixes this issue like this:
1. Text #tag text
        ^ backspace here
2. Text#tag text
       ^ space
3. Text #tag text
        ^ tag suggestion opens
2024-02-27 09:16:56 +08:00
ercd 1ae9bf23a0 fix: telegram callback query handler dereferencing nil pointer if memo not found (#3003)
* fix: telegram callback query handler dereferencing nil pointer if memo not found

* chore: add an answer to callback query if memo not found
2024-02-27 00:03:08 +08:00
Zhiyuan Zheng 51a7934616 fix: firefox/safari to redirect to /explore in HomeLayout (#3001) 2024-02-26 13:38:24 +08:00
Mr. Lin 8d08cfe1c9 fix: incorrectly checking whether registration is allowed in the login v1 api (#2998)
fix: Incorrectly checking whether registration is allowed in the login interface, resulting in the inability to log in through apiv1
2024-02-26 13:36:17 +08:00
Steven b0f52ade7a chore: remove metric service 2024-02-24 23:32:39 +08:00
Steven 222d04fb22 chore: add fuse to get tag suggestions 2024-02-24 11:02:46 +08:00
Steven 68468927dd chore: tweak setting styles 2024-02-24 11:01:57 +08:00
Steven dfe29ec766 chore: tweak route layout 2024-02-24 10:18:53 +08:00
Steven db56e1b575 chore: fix user banner dropdown 2024-02-23 23:47:26 +08:00
Steven 5b92ac1775 chore: fix setting migrator 2024-02-23 09:16:34 +08:00
Steven f2eb9f1b8f chore: fix get workspace setting 2024-02-23 09:11:39 +08:00
Steven e602aeecc1 fix: update workspace general setting 2024-02-23 09:08:49 +08:00
Steven ce133ad69b chore: retire unused workspace settings 2024-02-23 08:40:33 +08:00
Steven e585578553 chore: tweak readme 2024-02-23 08:25:54 +08:00
Steven 4d9c929c32 chore: upgrade gomark 2024-02-23 08:22:39 +08:00
Steven 39bf850591 fix: embed memos callback 2024-02-22 23:17:15 +08:00
Steven 9cd835b979 chore: upgrade gomark wasm 2024-02-22 23:11:32 +08:00
Steven 0afdbe3332 chore: remove animation of spoiler 2024-02-22 19:25:24 +08:00
Steven 6b14d87521 chore: fix linter 2024-02-21 23:45:12 +08:00
Steven 51d58d3982 chore: add workspace setting migrator 2024-02-21 23:43:18 +08:00
Steven 4378816e44 chore: tweak i18n 2024-02-21 23:02:18 +08:00
Steven e7bbd850b2 chore: tweak spoiler animation 2024-02-21 21:31:34 +08:00
Steven c6162d3f38 chore: update dependencies 2024-02-21 21:24:31 +08:00
Steven ce32206677 chore: remove unused system setting 2024-02-21 21:15:28 +08:00
Steven 50a3af3b29 chore: fix get general setting 2024-02-21 20:44:35 +08:00
Steven 80b64c02fd chore: tweak workspace setting seeds 2024-02-21 20:25:25 +08:00
Steven 13b911ebf0 chore: add spoiler node 2024-02-20 23:55:54 +08:00
Steven 4a6da91719 chore: fix serve frontend flag 2024-02-20 23:24:13 +08:00
Steven fa62e8b59a chore: tweak linter errors 2024-02-20 23:07:42 +08:00
Steven 8e11826db1 chore: update workspace setting service 2024-02-20 23:02:01 +08:00
David Nguyen e6d0c00cf6 chore: update vi.json (#2980) 2024-02-20 17:57:06 +08:00
Kristián 03d67d5a00 feat: add mermaid support in codeblock (#2971) 2024-02-19 15:10:58 +08:00
Kazuki H a86117f613 feat: add new line if the cursor is on a character when adding a tag (#2960) 2024-02-19 08:54:47 +08:00
Søm fc1a2cf2fc chore: update ja.json (#2966) 2024-02-17 09:31:52 +08:00
Steven d22b772232 chore: add memo actions to memo detail page 2024-02-15 11:16:51 +08:00
Steven f1ec5775a7 chore: update inbox props 2024-02-14 09:44:35 +08:00
Bryan 4aa4417d91 chore: allow all 20x response status code in webhook (#2947) 2024-02-13 09:30:48 +08:00
Steven 606e574e19 chore: update enum type 2024-02-13 09:30:28 +08:00
Brilliant Hanabi ebe3678288 feat: add visibility select in ShareMemoDialog (#2941)
In ShareMemoDialog, user can change the visibility
of the memo, so that the memo can be set to public
to be viewed by anyone with the link.
2024-02-13 09:28:16 +08:00
Steven b3ca9969c4 chore: tweak linter 2024-02-09 22:18:55 +08:00
Steven 3dddd3ec4c chore: tweak reaction store 2024-02-09 21:59:45 +08:00
Brilliant Hanabi 81aa9b107f feat: add notice when sharing private links in MemoDetail (#2942) 2024-02-09 09:30:01 +08:00
Steven 60efd3ac32 chore: tweak memo view 2024-02-08 22:52:49 +08:00
Steven 4081a6f5ad chore: add more reactions 2024-02-08 21:20:51 +08:00
Lincoln Nogueira 334e489867 chore: improve docker-compose.dev (#2938) 2024-02-08 16:28:43 +08:00
Steven c7822515a1 chore: tweak view checks 2024-02-08 13:37:38 +08:00
Steven d86f0bac8c chore: implement reaction frontend 2024-02-08 13:25:15 +08:00
Steven e5f244cb50 chore: fix tests 2024-02-08 11:58:23 +08:00
Steven 3a5bc82d39 chore: implement reaction service 2024-02-08 11:54:59 +08:00
Steven a4fa67cd18 chore: update dependencies 2024-02-08 08:13:42 +08:00
Steven 43a2d6ce09 chore: tweak user setting 2024-02-08 08:06:55 +08:00
Mehad Nadeem d2434111b4 chore: impl compact mode setting (#2935)
* chore: backend/DB related files for compact view setting.

* fix: passing lint errors

* fix2: passing linter errors
2024-02-08 08:05:56 +08:00
Steven 559e427c50 chore: implement reaction store 2024-02-07 23:40:23 +08:00
Steven 99568236a3 chore: run buf generate 2024-02-07 21:51:30 +08:00
Mehad Nadeem 06fb2174c3 feat: add compact mode setting (Proto) (#2934)
* chore: proto related files for compact view setting.

* fix: pasing lint errors
2024-02-07 21:45:11 +08:00
Kazuki H 5ac17fc012 fix: displaying archived memos (#2933)
* fix: web: Archived: Show displayTime instead of updateTime

Archiving a memo is considered "updating" it, so the time it was
archived will be displayed, instead of the time it was created.

* fix: web: Archived: Add an option to fetch more memos

Just like on other pages, add a button to fetch more memos. Otherwise,
the user would only be able to load the latest 10 memos, as defined in
DEFAULT_MEMO_LIMIT.
2024-02-07 17:53:23 +08:00
Steven a76b86f18a chore: fix highlight code 2024-02-06 20:59:17 +08:00
Steven ded8001735 chore: fix v2 routes 2024-02-06 20:55:27 +08:00
Steven 185ec2ad2a chore: update inbox service 2024-02-06 19:46:25 +08:00
Steven 6b59c7670c chore: fix linter warning 2024-02-05 23:32:01 +08:00
Steven 434ef44f8c chore: add cookie builder 2024-02-05 23:28:29 +08:00
Steven 46ea16ef7e chore: fix cookie attrs 2024-02-05 22:14:58 +08:00
Steven 8f15e8773a chore: update cookie attrs 2024-02-05 21:42:23 +08:00
Steven 25efc33b24 chore: tweak timeline styles 2024-02-05 21:37:43 +08:00
Steven ba460382b0 chore: remove type-gen script 2024-02-05 20:42:01 +08:00
Steven e35225ff24 chore: fix resource url 2024-02-05 19:35:23 +08:00
Steven 397a7f00ef chore: add postinstall script 2024-02-05 19:29:47 +08:00
Steven 06eff151e7 chore: tweak memo find builder 2024-02-05 06:40:55 +08:00
Steven c30d7ab8f3 chore: update cors middleware 2024-02-05 06:10:10 +08:00
Steven ab4a670bec chore: add env example 2024-02-05 00:33:07 +08:00
Steven ce663efc14 chore: update cookie attrs 2024-02-05 00:11:36 +08:00
Steven 9e72432f19 chore: tweak cookie attrs 2024-02-05 00:10:54 +08:00
Steven b056c59dea chore: add vercel.json 2024-02-05 00:01:31 +08:00
Steven 15c90871d9 chore: update request base url 2024-02-04 23:48:26 +08:00
Steven be899cd027 chore: update eslint config 2024-02-04 22:52:47 +08:00
Steven 8773a3d2c1 chore: tweak assets folder 2024-02-04 22:45:51 +08:00
Steven d2603ee67b chore: upgrade frontend dependencies 2024-02-04 21:36:11 +08:00
Steven c92507728a chore: tweak filter checks 2024-02-04 21:07:14 +08:00
Steven eb4f7b47b7 chore: update memo find builder 2024-02-04 20:54:17 +08:00
Steven 1e07b70d23 chore: fix export memos 2024-02-04 20:20:14 +08:00
Athurg Gooth b8a9783db5 fix: signin error notification is not shown (#2908)
fix signin error notification is not shown
2024-02-04 14:25:51 +08:00
Ikko Eltociear Ashimine 82e72813f9 chore: fix typo in About.tsx (#2899) 2024-02-04 08:33:13 +08:00
Steven 57510ddee5 chore: update readme with used resources 2024-02-03 23:42:24 +08:00
Steven 00c47a0673 chore: fix menu z-index 2024-02-03 23:17:03 +08:00
Steven 374f3f7d96 chore: fix filter initial state 2024-02-03 22:03:56 +08:00
Steven 8340e6b247 chore: upgrade gomark 2024-02-03 21:52:54 +08:00
Steven 7f5148d490 chore: clean dropdown 2024-02-01 21:56:08 +08:00
Steven c522e1450a chore: update codeblock style 2024-02-01 21:38:28 +08:00
Steven c342c464a2 chore: update services comment 2024-02-01 21:26:09 +08:00
Steven f6f193af2d chore: format proto 2024-02-01 21:15:56 +08:00
Steven dd06278692 feat: add batch upsert tags 2024-02-01 21:13:42 +08:00
Steven fdd17ce849 chore: update memo content key 2024-02-01 20:40:43 +08:00
Elliot Chen 7cd3fcbc61 fix: wrong order of the timeline in the resource page & add webhook when create memos using Telegram bot (#2886)
* fix: wrong order in resource page timeline

* feat: add webhook when create memos using Telegram bot

* rename variables and fix typos for static checks
2024-02-01 20:24:58 +08:00
Steven e78311b3af fix: initial gomark wasm 2024-02-01 19:39:41 +08:00
Steven e3afad74ce fix: update initial wasm 2024-02-01 19:27:54 +08:00
Steven 554f93eccc fix: move initial wasm into app 2024-02-01 19:06:44 +08:00
Steven 79227021f5 chore: bump version 2024-01-31 23:08:33 +08:00
Steven b4f2a3bd14 chore: remove migrator 2024-01-31 22:58:43 +08:00
Steven 0b4914d880 chore: update generated node types 2024-01-31 22:42:51 +08:00
Steven 2f0b0e0071 chore: remove node definition 2024-01-31 22:32:09 +08:00
Steven 8ce6a32aac feat: use gomark wasm in frontend 2024-01-31 22:25:24 +08:00
Wen Sun 3158c4b8b5 fix: role error in api/v2 when the first user registers (#2875)
Fix role error in api/v2 when the first user registers
2024-01-31 19:55:52 +08:00
Steven 30ae4140f3 chore: update gomark source 2024-01-31 19:01:08 +08:00
Lincoln Nogueira 279cba0e6b chore: greatly speed up migrator and lower memory usage (#2874)
* chore: add en-GB language

* chore: remove en-GB contents

* chore: prevent visitors from breaking demo
- prevent disabling password login
- prevent updating `memos-demo` user
- prevent setting additional style
- prevent setting additional script
- add some error feedback to system settings UI

* Revert "chore: add en-GB language"

This reverts commit 2716377b04.

* chore: speed-up migrator and lower memory usage
- remove all Store indirections
- query database directly with prepared statements

* chore: fix golangci-lint warnings
2024-01-31 16:45:21 +08:00
Lincoln Nogueira 52539fc130 chore: prevent visitors from breaking demo (#2869)
* chore: add en-GB language

* chore: remove en-GB contents

* chore: prevent visitors from breaking demo
- prevent disabling password login
- prevent updating `memos-demo` user
- prevent setting additional style
- prevent setting additional script
- add some error feedback to system settings UI

* Revert "chore: add en-GB language"

This reverts commit 2716377b04.
2024-01-31 13:16:31 +08:00
Steven 49e3eb107c chore: update gomark wasm 2024-01-31 00:25:01 +08:00
Lincoln Nogueira e7d5dfe515 chore: add en-GB language (#2865)
* chore: add en-GB language

* chore: remove en-GB contents
2024-01-30 23:39:13 +08:00
Steven 28c7a75ea2 chore: fix import nodes 2024-01-30 22:15:05 +08:00
Steven 59d69a05fa feat: initial gomark wasm importer 2024-01-30 22:12:44 +08:00
Steven ad2d492dec chore: move preview memo content 2024-01-30 22:10:17 +08:00
Elliot Chen bee6f278ba fix: the same-storage check in the new pre-sign feature (#2860)
* fix: error check for the same oss-storage

* fix: conflict error2 variable in code refactor in s3.go

* chore: rename endpointUrl to endpointURL
2024-01-30 19:07:16 +08:00
Brilliant Hanabi 1bad0543d0 feat: add notice when sharing private links (#2809)
Co-authored-by: boojack <stevenlgtm@gmail.com>
2024-01-30 19:06:30 +08:00
Noah Alderton 73337331cb feat: export all user Memos as a .zip of Markdown files (#2854)
* Add gRPC Memos Export

* Update code style

* Add URL.revokeObjectURL

* Rename protobuf and ESLint fix

* Change MemosExport to ExportMemos
2024-01-30 16:42:54 +08:00
Wen Sun 50f7f131ea fix: month grouping error in timeline page (#2861) 2024-01-30 07:56:03 +08:00
Steven a16bde23f7 chore: tweak variable name 2024-01-29 23:15:47 +08:00
Steven c5a5f67fdb refactor: migrate auth service 2024-01-29 23:12:02 +08:00
Steven de8db63811 chore: rename workspace setting service 2024-01-29 22:43:40 +08:00
Steven dd9ee44a1f docs: regenerate swagger 2024-01-29 22:05:33 +08:00
Aleksandr Baryshnikov fa17dce046 feat: pre-signed URL for S3 storage (#2855)
Adds automatically background refresh of all external links if they are belongs to the current blob (S3) storage. The feature is disabled by default in order to keep backward compatibility.

The background go-routine spawns once during startup and periodically signs and updates external links if that links belongs to current S3 storage.

The original idea was to sign external links on-demand, however, with current architecture it will require duplicated code in plenty of places. If do it, the changes will be quite invasive and in the end pointless: I believe, the architecture will be eventually updated to give more scalable way for pluggable storage. For example - Upload/Download interface without hard dependency on external link. There are stubs already, but I don't feel confident enough to change significant part of the application architecture.
2024-01-29 21:12:29 +08:00
Steven cbcec80c5d chore: fix import order 2024-01-29 21:08:30 +08:00
Steven 2b7bd47b44 fix: rss routes 2024-01-29 21:04:35 +08:00
Steven 54c5039db3 chore: fix golang linter 2024-01-29 19:17:25 +08:00
Steven af646ce2de refactor: move gomark 2024-01-29 19:14:46 +08:00
Steven f4ac7ff529 chore: update memo resource url 2024-01-28 23:02:38 +08:00
Steven 55ecdae509 chore: fix auto link matcher 2024-01-28 22:13:19 +08:00
Steven ef73299340 chore: update resource name migrator 2024-01-28 21:40:24 +08:00
Steven 8c6292925e chore: update code block styles 2024-01-28 15:41:11 +08:00
Steven f05a89315c chore: fix list memos 2024-01-28 08:38:29 +08:00
Steven a4452d8a2f chore: update linter rules 2024-01-28 08:17:11 +08:00
Steven 5e74394643 chore: add resource name migrator 2024-01-28 07:58:53 +08:00
Steven f4e722c516 chore: remove latest tag 2024-01-28 07:46:08 +08:00
Steven 12275c6a34 chore: fix linter warning 2024-01-28 07:38:01 +08:00
Steven 21ef5a9bc0 chore: tweak workspace service 2024-01-28 07:35:42 +08:00
Steven 87b23940a6 chore: upgrade backend dependencies 2024-01-28 07:13:11 +08:00
Steven 11dd23f59b chore: tweak link checks 2024-01-28 07:04:35 +08:00
Lincoln Nogueira 887903b66b feat: add buf plugin to generate openapiv2 spec (#2843) 2024-01-28 06:16:37 +08:00
Steven 309fab222e chore: implement nested blockquote 2024-01-27 21:38:07 +08:00
Steven 1dc4f02b64 chore: update memo requests 2024-01-27 20:35:48 +08:00
Steven 8db90a040c chore: remove unused dependencies 2024-01-27 20:20:36 +08:00
Steven 932f636d84 chore: update codeblock renderer 2024-01-27 19:09:10 +08:00
Steven ed32b20c9e chore: update frontend dependencies 2024-01-27 17:28:06 +08:00
Steven 10d709c167 chore: fix highlight cursor 2024-01-27 12:35:01 +08:00
Steven 8455114eef chore: fix list memos request 2024-01-27 11:17:59 +08:00
Steven c26109cd36 chore: update list memos request 2024-01-27 11:14:17 +08:00
Steven 4b223c1e4c chore: update collapse sidebar 2024-01-27 05:27:42 +08:00
Steven b9cbe6626f chore: update tag rename 2024-01-27 05:26:32 +08:00
Steven 566171783d chore: tweak embedded memo style 2024-01-26 23:33:40 +08:00
Steven 7edb3598ea chore: update default request limit 2024-01-26 23:03:10 +08:00
Steven bc2d2d0cde feat: support set embedded content in UI 2024-01-26 22:51:57 +08:00
Steven e1977df14b chore: remove check underscores 2024-01-26 21:23:36 +08:00
Wei Zhang ddc89029b7 fix: use mysql to parse dsn (#2838)
Signed-off-by: Zhang Wei <kweizh@gmail.com>
2024-01-26 13:43:48 +08:00
Steven f8b9a83d4a chore: tweak default value 2024-01-26 09:22:47 +08:00
Steven 2f16b7065a chore: tweak scripts 2024-01-26 09:15:27 +08:00
Steven e5ff1829a5 chore: add Hungarian locale 2024-01-26 08:44:12 +08:00
Steven d7889d9903 chore: tweak url filters 2024-01-26 08:39:53 +08:00
Steven db3457e081 chore: bump version 2024-01-26 08:30:22 +08:00
Steven 4f2b00b4f3 chore: add migration scripts 2024-01-26 08:29:11 +08:00
Steven 79558028c0 feat: implement rename tag 2024-01-25 23:09:35 +08:00
Steven 70d1301dc3 chore: use filter in url params 2024-01-25 20:05:47 +08:00
Steven 6d5e1def76 chore: update member section 2024-01-25 19:49:39 +08:00
boojack a5bc2d0ed6 chore: update i18n from Weblate (#2832)
* Added translation using Weblate (Hungarian)

* Translated using Weblate (Hungarian)

Currently translated at 0.3% (1 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

* Translated using Weblate (Hungarian)

Currently translated at 71.2% (226 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hu/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: Vermunds <com.github@weylus.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: ti777777 <ti12272198686@yahoo.com.tw>
2024-01-25 19:36:02 +08:00
Steven 08ac60cc70 chore: update memo relation dialog 2024-01-25 08:59:10 +08:00
Mudkip f654d3c90e fix: encode filename when using url prefix for resources (#2829)
* fix: encode filename when using url prefix for resources

* fix: only encode the last parts of filename

* fix: encode all parts in filepath
2024-01-24 11:28:26 +08:00
Steven 1b69b73eb9 chore: update calendar styles 2024-01-23 23:15:54 +08:00
Steven 3dbb254aeb chore: update referenced memo title from params 2024-01-23 21:54:15 +08:00
Steven fdb1779a59 chore: implement referenced content renderer 2024-01-23 21:47:17 +08:00
Steven a316e239ce chore: implement referenced content node 2024-01-23 21:40:59 +08:00
Steven d7f02b94e5 chore: fix linter 2024-01-23 21:27:05 +08:00
Steven d165d87288 refactor: markdown parser matchers 2024-01-23 21:23:40 +08:00
Steven bf905bba86 chore: remove unused date picker 2024-01-22 22:50:27 +08:00
Brilliant Hanabi 3a129d5cfb fix: avoid making memos public when disabled (#2816)
* fix: avoid making memos public when disabled in v2

* fix: avoid making memos public when disabled in v1
2024-01-22 20:51:33 +08:00
ti777777 024a818e91 chore: update zh-Hant (#2815) 2024-01-21 23:50:44 +08:00
Steven 54a24833a7 chore: fix resource seeds 2024-01-21 21:36:31 +08:00
Steven a620d140c5 chore: update embedded content renderers 2024-01-21 21:27:04 +08:00
Steven 370054e040 chore: implement collapsed navigation 2024-01-21 21:02:55 +08:00
Steven fae0b4e900 chore: update memo relation style 2024-01-21 11:22:25 +08:00
Steven c38404b5d5 chore: tweak get memo by name 2024-01-21 10:57:53 +08:00
Steven 4d48f50815 chore: use resource name in frontend 2024-01-21 10:55:49 +08:00
Steven 582cc6609c feat: add user-defined id to resource 2024-01-21 10:49:30 +08:00
Steven 40bd75c725 fix: create memo with resource name 2024-01-21 10:33:31 +08:00
Steven b2fc3076f6 chore: update memo store 2024-01-21 01:23:55 +08:00
Steven 288527914b chore: migrate memo route 2024-01-21 01:23:44 +08:00
Steven a2aea3747c chore: remove server tests 2024-01-20 23:51:24 +08:00
Steven 8382354ef7 feat: add user-defined name to memo 2024-01-20 23:48:35 +08:00
Steven 264e6e6e9c chore: tweak file name 2024-01-20 23:47:04 +08:00
Steven eb72609ea3 chore: update memo editor cache key 2024-01-20 20:52:11 +08:00
Brilliant Hanabi 776785ac90 chore: update zh-Hans & zh-Hant translations (#2804) 2024-01-20 20:27:20 +08:00
Steven d5f874e185 chore: handle resource not found 2024-01-20 12:47:43 +08:00
Steven 89d940d9b7 feat: implement params field for embedded content node 2024-01-20 12:41:08 +08:00
Mark Zhao bd1cf62761 feat: enable iframe rendering in markdown code block (#2799)
* enable iframe rendering in code block

* fix eslint issue
2024-01-20 11:36:45 +08:00
Steven 196facfacd feat: implement embedded resource renderer 2024-01-20 09:17:31 +08:00
Steven afe75fd9f2 chore: fix tokens split tests 2024-01-20 02:09:33 +08:00
Steven 8a34013558 feat: implement embedded memo renderer 2024-01-20 01:56:10 +08:00
Steven 67f5ac3657 feat: implement subscript and superscript renderer 2024-01-19 23:10:16 +08:00
Steven 7236552b6c feat: implement subscript and superscript parsers 2024-01-19 23:06:22 +08:00
Steven 1f5899d238 chore: update dependencies 2024-01-19 19:20:59 +08:00
Wen Sun ec4884ea04 fix: incorrect timeline month display (#2792)
Fix incorrect timeline month display
2024-01-19 18:07:08 +08:00
Elliot Chen 2e0619b4dc feat: add a webhook action for deleted memos (#2791) 2024-01-19 09:56:00 +08:00
Steven c9146bc749 chore: update code style 2024-01-19 07:06:28 +08:00
Steven f5b5bd64bc chore: tweak datetime.ts 2024-01-18 22:18:56 +08:00
Steven d31d9eb71c chore: remove unused nil checks 2024-01-18 19:23:45 +08:00
Steven f28b654057 chore: fix setting nil checks 2024-01-18 19:20:48 +08:00
Steven 8738b68a44 chore: tweak readme 2024-01-18 19:06:49 +08:00
Steven 42381fa154 chore: add stable build action 2024-01-18 18:49:06 +08:00
Steven 22427101f8 chore: add stale issue action 2024-01-18 16:18:18 +08:00
Steven 2a4ebf5774 chore: add search bar in archived page 2024-01-18 15:28:37 +08:00
Steven 5172e4df7c chore: create memo visibility when creating 2024-01-18 15:20:22 +08:00
Steven 893dd2c85e chore: add disable filter to renderer context 2024-01-18 14:52:57 +08:00
Steven d426f89cf0 chore: add time filter to timeline 2024-01-18 14:30:20 +08:00
Steven 7de3de5610 chore: fix go test warning 2024-01-18 11:45:59 +08:00
Steven 2856e66609 chore: fix go test 2024-01-18 11:42:57 +08:00
Steven 354011f994 chore: handle filter in user profile page 2024-01-18 11:38:45 +08:00
Steven 8ed827cd2d chore: update table node delimiter 2024-01-18 11:36:13 +08:00
Steven 05c0aeb789 feat: implement table renderer 2024-01-18 10:49:28 +08:00
Steven aecffe3402 feat: implement table parser 2024-01-18 10:21:08 +08:00
Mehad Nadeem 70e6b2bb82 chore: added tooltip for vacuum button (#2778)
* chore: added tooltip for vacuum button

- At the moment only has text for English language therefore other JSON files need to be updated accordingly

* Update en.json
2024-01-18 08:09:49 +08:00
Steven 54296f0437 chore: update filter in timeline 2024-01-18 08:06:59 +08:00
Steven 8fcd9332f7 chore: tweak timeline styles 2024-01-17 22:32:58 +08:00
Steven 1857362d03 fix: locale and appearance setting 2024-01-17 22:16:12 +08:00
Steven 6d7186fc81 feat: rebuild timeline page 2024-01-17 21:59:49 +08:00
Wen Sun e4488da96e fix: signup is not allowed if password login is disabled (#2776)
Signup is not allowed if password login is disabled

If password login is disabled in the system configuration, the "signup" in the "/auth" page disappears, but the user can manually enter "/auth/signup" to access the system by creating a new user.
2024-01-17 10:49:22 +08:00
Steven cc43d06d33 chore: update memo stats response 2024-01-17 09:17:33 +08:00
Steven 9ffd827028 fix: appearance and locale initial value 2024-01-16 22:53:45 +08:00
Hanqin Guan 15e6542f0d fix: server overrides user's locale/appearance (#2771) 2024-01-16 18:21:08 +08:00
Noah Alderton 24bb3e096a fix: DatePicker by passing in Timezone to API (#2770)
* Fix DatePicker by passing in Timezone to API

* Add some clarity
2024-01-16 18:02:09 +08:00
Lincoln Nogueira 5bcbbd4c52 chore: fix store tests on Windows (#2769)
It's just a matter of explicitly closing the database, so that TempDir.removeAll doesn't fail.
2024-01-16 13:51:26 +08:00
Noah Alderton ff13d977e9 feat: add URL paste handler (#2768)
* feat: Add URL paste handler

* Check if text highlighted for URL pasting
2024-01-16 10:06:16 +08:00
Wen Sun 1fdb8b7b01 fix: apply customized profile name in mobile header (#2723)
Fix mobile header title, apply customized profile name
2024-01-16 09:04:03 +08:00
Wen Sun f1ee88c4e1 fix: display system logo in user banner if user not logged in (#2747)
Display system logo in user banner if user not logged in
2024-01-16 09:03:27 +08:00
Noah Alderton b578afbc6a fix: DatePicker Local Date (#2766)
Fix DatePicker Local Date
2024-01-16 08:35:48 +08:00
Steven ad94e8e3c6 feat: implement highlight renderer 2024-01-15 22:54:18 +08:00
Steven 3f4b361fad feat: implement highlight parser 2024-01-15 22:30:06 +08:00
Steven 46bd470640 chore: update favicon 2024-01-15 21:10:41 +08:00
Steven fdbf2d8af2 chore: fix blockquote renderer 2024-01-15 20:41:37 +08:00
Steven 5a723f00fa chore: split editor keydown handler 2024-01-15 20:33:42 +08:00
Noah Alderton 728a9705ea feat: Markdown Editor Keyboard Shortcuts (#2763)
* Add bold and italic keyboard shortcut

* Add hyperlink keyboard shortcut support
2024-01-15 20:19:59 +08:00
THELOSTSOUL cd3a98c095 fix: change use-set priority (#2760)
The user settings(locale, appearance) are not in use when restart broswer
2024-01-15 20:08:14 +08:00
Wen Sun a22ad90174 fix: set memo resources error in mysql (#2761)
Fix error updating memo resources in mysql
2024-01-15 20:05:07 +08:00
Steven 5ebbed9115 chore: handle tag click 2024-01-15 08:15:34 +08:00
Steven 7ae4299df2 chore: implement create resource 2024-01-15 08:13:06 +08:00
Noah Alderton 3d23c01e26 feat: add additional favicon formats (#2752)
Add additional favicons
2024-01-15 07:54:33 +08:00
Lincoln Nogueira 089e04bcfd chore: use webp compression on logo (#2756)
- Logo size reduced from 310 KB to 36 KB.
- Point metadata image URL to local logo instead of remote
2024-01-14 22:21:03 +08:00
Steven 98762be1e5 feat: implement indent for list nodes 2024-01-14 22:19:03 +08:00
Steven d44e74bd1e chore: update editor actions 2024-01-14 21:47:03 +08:00
Steven 8e0ce4d678 fix: list memos with pinned 2024-01-14 20:51:52 +08:00
Steven 45cf158508 chore: fix max width of home section 2024-01-14 20:25:45 +08:00
Anish Kelkar 7340ae15f7 chore: delete .vscode directory (#2693)
* Delete .vscode directory

* web/.vscode deleted
2024-01-14 20:12:57 +08:00
Steven 6db7ad76da chore: update tag selector 2024-01-13 16:26:42 +08:00
Steven 4a407668bc chore: tweak dialog close button 2024-01-13 15:33:23 +08:00
Steven ab1fa44f00 feat: implement markdown buttons 2024-01-13 15:09:06 +08:00
Steven cd0004cf88 chore: update icon version 2024-01-13 15:08:58 +08:00
Steven 667aaf06a0 chore: update dependencies 2024-01-13 14:33:50 +08:00
Steven a8074d94e8 chore: update image attrs 2024-01-13 14:08:36 +08:00
Hanqin Guan 16e68fbfff fix: duplicated/reflexive relation in v2 api. (#2750) 2024-01-13 07:21:19 +08:00
Wen Sun 81942b3b98 chore: updating the default scopes of GitHub SSO (#2746)
Updating the default scopes of GitHub SSO

The scope of "user" in GitHub OAuth includes permissions to update a user's profile.
2024-01-12 14:02:11 +08:00
Athurg Gooth a7cda28fc7 fix: filename with space (#2745) 2024-01-12 14:01:19 +08:00
Steven 0c52f1ee6a chore: tweak home style 2024-01-12 08:08:24 +08:00
Steven 1994c20c54 chore: tweak setting page 2024-01-11 22:25:05 +08:00
Steven a1dda913c3 chore: fix tag selector position 2024-01-11 21:36:22 +08:00
Athurg Gooth d626de1875 fix: pnpm install failed in docker (#2732)
fix pnpm install failed in docker
2024-01-11 21:29:55 +08:00
Wen Sun 6cfd94cc69 fix: deleting inbox records that senders have been deleted (#2743)
Deleting inbox records that senders have been deleted
2024-01-11 21:29:22 +08:00
Athurg Gooth 79b68222ff chore: set image loading to lazy (#2733)
set image loading to lazy to avoid concurrent problem
2024-01-11 10:27:18 +08:00
Steven aaec46a39c chore: update find memo with updated time 2024-01-10 00:10:59 +08:00
Steven 9c663b1ba2 fix: merge mysql dsn with params 2024-01-10 00:03:47 +08:00
Steven 777ed899a3 chore: add memo uid 2024-01-08 21:48:26 +08:00
Steven ddcf1d669d chore: add max content length 2024-01-08 21:17:21 +08:00
Steven 32d02ba022 chore: fix horizontal rule matcher 2024-01-08 21:00:45 +08:00
Steven 5449342016 fix: auto link converters 2024-01-08 20:57:44 +08:00
Noah Alderton 43e42079a4 feat: export Memos as Markdown FIles (#2716) 2024-01-08 11:40:50 +08:00
Steven cafa7c5adc chore: update backend dependencies 2024-01-06 19:46:35 +08:00
Steven 1258c5a5b0 chore: update workspace setting proto 2024-01-06 19:46:21 +08:00
Steven 83141f9be2 chore: tweak navigation styles 2024-01-06 19:12:26 +08:00
Steven 4c59035757 chore: update about page 2024-01-06 19:01:11 +08:00
Steven 9459ae8265 chore: update postgres stmt builder 2024-01-06 17:12:10 +08:00
Steven 8893a302e2 chore: update logs 2024-01-06 16:58:58 +08:00
Steven d67eaaaee2 chore: update database migrator 2024-01-06 16:55:13 +08:00
Steven fd8333eeda chore: fix memo parent_id 2024-01-06 13:22:02 +08:00
Steven f5a1739472 chore: update memo detail checks 2024-01-06 10:03:36 +08:00
Steven a297cc3140 chore: exclude comments in memo list response 2024-01-06 09:48:11 +08:00
Steven 79c13c6f83 chore: fix edit memo params 2024-01-06 09:25:17 +08:00
Steven 8b9455d784 chore: fix memo resources position 2024-01-06 09:23:20 +08:00
Steven 501f8898f6 chore: fix postgres stmts 2024-01-05 21:27:16 +08:00
Steven ee13927607 chore: fix restore tag node 2024-01-05 18:50:28 +08:00
Steven d2a9aaa9d4 chore: update line break renderer 2024-01-05 09:18:37 +08:00
Steven f563b58a85 chore: fix renderer props 2024-01-05 08:47:43 +08:00
Steven ce2d37b90c chore: fix find sibling node 2024-01-05 08:43:30 +08:00
Steven 454cd4e24f feat: implement switchable task list node 2024-01-05 08:40:16 +08:00
Steven 6320d042c8 chore: update home padding styles 2024-01-04 22:50:46 +08:00
Steven d7ed59581c chore: fix math block matcher 2024-01-04 21:50:13 +08:00
Steven 9593b0b091 chore: fix link rel field 2024-01-04 21:26:56 +08:00
Steven ca53630410 chore: update drawer background 2024-01-04 21:11:22 +08:00
Steven f484c38745 chore: fix dependencies 2024-01-04 20:07:53 +08:00
Steven d12a2b0c38 feat: implement math expression parser 2024-01-04 20:05:29 +08:00
Steven c842b921bc chore: update backend dependencies 2024-01-04 19:15:25 +08:00
Wen Sun 6b2eec86c2 fix: image upload failed with cloudflare R2 (#2704)
Fix image upload failed with cloudflare R2
2024-01-04 19:08:54 +08:00
Steven 2eba4e2cd4 chore: update version 2024-01-04 08:36:45 +08:00
Steven 73baeaa0ad chore: tweak dark mode styles 2024-01-04 08:32:14 +08:00
Steven c58851bc97 chore: tweak accent color 2024-01-03 23:30:28 +08:00
Steven 96140f3875 chore: tweak dark mode styles 2024-01-03 23:12:50 +08:00
Lincoln Nogueira 369b8af109 chore: improve resource internal_path migrator (#2698)
* chore: improve internal path migrator
- handle mixed path styles
- handle Windows paths
- add tests

* chore: fix goimports error
2024-01-03 08:31:59 +08:00
Steven 914c0620c4 chore: add statistics view 2024-01-03 08:22:32 +08:00
Steven 138b69e36e chore: fix memo comment 2024-01-03 08:19:38 +08:00
Elliot Chen 3181c076b2 feat: add {uuid} in path template when using local storage or S3 (#2696)
Add {uuid} in path template when using local storage or S3

Add an addition tag `{uuid}` to the `replacePathTemplate`.

It is a workaround to leak the public links of a resource when using S3-based object storage. Currently, all resource blobs stored in S3 (R2, OSS) are set to be public. It is insecure as the resources for the private memos are also accessible on the Internet. Using an additional {uuid} might reduce this risk.

Meanwhile, it is also possible to avoid filename conflict
2024-01-02 20:57:55 +08:00
Noah Alderton 673809e07d fix: docker-compose.dev.yaml (#2695)
* Fix docker-compose.dev.yaml

* Add newline to .gitignore
2024-01-02 18:33:19 +08:00
Steven f74fa97b4a chore: traverse nodes to upsert tags 2024-01-02 08:56:30 +08:00
Steven c797099950 chore: update resource internal path migrator 2024-01-02 08:29:18 +08:00
Steven 0f8bfb6328 chore: update index.html 2023-12-29 08:28:17 +08:00
Steven 4cd01ece30 chore: update frontend metadata 2023-12-29 08:19:32 +08:00
Lincoln Nogueira 14b34edca3 chore: fix misuse of package path instead of filepath.path (#2684)
As stated by https://pkg.go.dev/path, "path" is mainly for URLs, "path.filepath" for file systems
2023-12-29 07:50:15 +08:00
Lincoln Nogueira 411e807dcc chore: use consistent relative paths for resources (#2683)
- always store resources with a relative path with forward slashes, which will be transformed as needed when the file is accessed

- fix an issue with thumbnail generation on Windows

- add several validations for local storage setting

- improve front-end error feedback when changing local storage

- add migrations to make existing resource paths relative (not needed, but improves database consistency)
2023-12-29 07:49:55 +08:00
Steven ea87a1dc0c chore: update memo content props 2023-12-28 22:57:51 +08:00
Steven 46f7cffc7b feat: implement restore nodes 2023-12-28 22:35:39 +08:00
Steven 2a6f054876 chore: update auto link parser 2023-12-28 21:32:44 +08:00
Steven 30dca18b79 chore: fix suspense wrapper 2023-12-28 08:34:06 +08:00
Steven 09c195c752 chore: update backend dependencies 2023-12-28 08:28:50 +08:00
Steven 2ae6d94e2c chore: update frontend dependencies 2023-12-28 08:27:06 +08:00
Steven 9ee4b75bbd chore: tweak memo detail styles 2023-12-27 23:25:02 +08:00
Steven cc40803b06 chore: update feature request template 2023-12-27 09:00:16 +08:00
Steven a0a03b0389 chore: tweak list memos request 2023-12-27 08:54:00 +08:00
Steven 0dfc367e56 chore: start grpc server 2023-12-27 08:50:02 +08:00
Steven c8d7f93dca feat: implement auto link parser 2023-12-27 08:44:51 +08:00
Steven 6fac116d8c chore: update user store 2023-12-26 23:05:33 +08:00
subks f48ff102c9 fix: eslint check failure after fixing #2672 (#2673) 2023-12-26 21:46:26 +08:00
subks bd5a0679ee fix: date format in share memo dialog (#2672)
fix: Date format in shareable Memo Images (#2668)
2023-12-26 17:50:09 +08:00
Steven fcfb76a103 chore: remove user urlsets in sitemap 2023-12-23 19:35:46 +08:00
Steven 8e325f9986 chore: return username in user response 2023-12-23 19:23:39 +08:00
Steven b8eaf1d57e chore: deprecate memo creation stats legacy api 2023-12-23 18:35:47 +08:00
Steven 42608cdd8f chore: fix server context 2023-12-23 17:59:15 +08:00
Steven 2cfa4c3b76 chore: tweak frontend routes register 2023-12-23 17:58:49 +08:00
Steven aa136a2776 chore: remove vite pwa plugin 2023-12-23 17:42:13 +08:00
Steven 68413a5371 chore: update frontend service 2023-12-23 17:04:52 +08:00
Steven 638f17a02c chore: update scripts 2023-12-23 15:12:25 +08:00
Steven 273d6a6986 chore: update dockerfile 2023-12-23 14:13:40 +08:00
Steven 953141813c chore: regenerate pnpm lock file 2023-12-23 12:01:26 +08:00
Leyang be2db3f170 feat: use vite plugin pwa for generate right sw.js (#2658)
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-12-23 12:00:03 +08:00
Steven eefce6ade3 chore: implement webhook dispatch in v2 api 2023-12-23 11:17:35 +08:00
Steven c6ebb5552e chore: add 403 page 2023-12-23 10:08:23 +08:00
Steven 4d64d4bf25 chore: upgrade frontend dependencies 2023-12-23 09:47:43 +08:00
Steven 2ee4d7d745 chore: add startTransition to links 2023-12-23 08:55:43 +08:00
Steven 1b81999329 chore: skip invalida setting checks 2023-12-23 08:55:23 +08:00
Steven df5aeb6d88 chore: remove v1 prefix in store name 2023-12-23 08:48:11 +08:00
Steven df3303dcd3 chore: update list users 2023-12-23 08:35:54 +08:00
Steven c267074851 chore: prevent archive/delete current user 2023-12-23 08:05:05 +08:00
Steven 21874d0509 chore: fix navigation errors 2023-12-23 08:01:16 +08:00
Steven 7898df2876 chore: update issue templates 2023-12-23 08:00:59 +08:00
Steven b2ec0d1217 chore: add skip cache requesting 2023-12-22 20:30:28 +08:00
Steven 5673e29e51 chore: compose memo in backend 2023-12-22 20:18:31 +08:00
Steven feefaabce9 chore: update heatmap click handler 2023-12-22 20:07:17 +08:00
Steven 29b540ade3 chore: fix fetch memos 2023-12-22 19:47:46 +08:00
Steven 919f75af1a chore: update suspense loading 2023-12-22 19:27:09 +08:00
Steven 17e905085f chore: update acl config 2023-12-22 09:11:55 +08:00
Steven 34af969785 chore: fix list memos order by pinned 2023-12-22 09:09:03 +08:00
Steven fd9c3ccbae chore: implement useMemoList store 2023-12-22 09:01:30 +08:00
Steven a3feeceace chore: remove component v1 suffix 2023-12-22 08:29:02 +08:00
Steven 02265a6e1a chore: fix memo search 2023-12-22 00:31:29 +08:00
Steven 81524c38e9 chore: refactor memo module 2023-12-21 23:40:43 +08:00
Steven 671551bdc1 chore: update memo detail page 2023-12-21 22:42:06 +08:00
Steven 10c81ccba3 chore: fix type definition 2023-12-21 21:43:28 +08:00
Steven 9361613f23 chore: update timeline page 2023-12-21 21:24:08 +08:00
Athurg Gooth b14334220f fix: trim the dirname of attachment send by telegram bot (#2651) 2023-12-21 09:47:57 +08:00
Athurg Gooth f184d65267 fix: attachments send from telegram lost (#2650) 2023-12-21 09:47:25 +08:00
Steven b64e2ff6ff chore: implement list memo resources api 2023-12-20 23:46:04 +08:00
Steven cbdae24314 chore: update archived page 2023-12-20 23:23:26 +08:00
Steven 762cb25227 chore: update memo service 2023-12-20 23:14:15 +08:00
Steven fc01a796f8 chore: fix demo seed data 2023-12-20 08:18:56 +08:00
Steven feb700f325 chore: clear access token when user not found 2023-12-20 07:42:02 +08:00
Steven 5334fdf1b2 chore: use api v2 in archived page 2023-12-19 23:49:24 +08:00
Steven abc14217f6 chore: tweak padding styles 2023-12-19 23:09:57 +08:00
Steven af68cae6ea chore: regenerate swagger docs 2023-12-19 22:37:07 +08:00
Steven e0cacfc6d6 chore: retire auto backup for sqlite 2023-12-19 22:34:06 +08:00
Steven b575064d47 chore: tweak padding 2023-12-19 21:44:40 +08:00
Steven 6290234ad1 chore: fix button styles 2023-12-19 21:29:07 +08:00
Steven aeed25648a chore: tweak drawer background 2023-12-19 08:55:21 +08:00
Steven 43e7506ed5 chore: fix react-uses import 2023-12-19 08:45:47 +08:00
Steven a3a1bbe8de chore: tweak responsible styles 2023-12-19 08:41:41 +08:00
Steven fe4ec0b156 chore: rename navigator 2023-12-19 00:13:22 +08:00
Steven 7c5fdd1b06 chore: remove demo banner 2023-12-18 23:46:48 +08:00
Steven 4d54463aeb chore: add mobile header 2023-12-18 23:33:09 +08:00
Steven 40bc8df63d chore: fix container height 2023-12-18 23:01:39 +08:00
Steven 61de7c8a32 chore: fix demo banner 2023-12-18 22:29:29 +08:00
Steven d6656db20d feat: implement part of full-screen layout 2023-12-18 22:10:36 +08:00
Steven 15a091fe4c chore: fix offset params in explore page 2023-12-18 20:54:51 +08:00
Steven d8a0528135 chore: tweak variable names 2023-12-18 20:47:29 +08:00
Steven 16fb5faebd chore: revert go mod update 2023-12-18 19:40:39 +08:00
Steven 2c4b5d75b3 chore: fix html escaping 2023-12-17 23:37:00 +08:00
Steven 770607f93f fix: add markdown service to acl 2023-12-17 11:37:38 +08:00
Steven db0eff4743 chore: clean frontend dependencies 2023-12-17 11:25:10 +08:00
Steven 0793f96578 chore: update heading styles 2023-12-17 11:08:13 +08:00
Steven 8095d94c97 chore: deprecate marked 2023-12-17 11:02:16 +08:00
Steven bcfcd59642 chore: deprecate old MemoContent 2023-12-17 10:58:22 +08:00
Steven 5d677c3c57 chore: implement node renderer components 2023-12-17 10:49:49 +08:00
Steven 28c0549705 feat: add markdown service 2023-12-17 09:53:22 +08:00
Steven bb42042db4 chore: implement task list parser 2023-12-16 12:48:52 +08:00
Steven 1c7fb77e05 chore: update user setting names 2023-12-16 12:18:53 +08:00
Steven e8ca2ea5a0 chore: rename renderer package 2023-12-16 11:57:36 +08:00
Steven e43a445c34 chore: implement escaping character node 2023-12-16 11:47:29 +08:00
Steven 1237643028 chore: update parser tests 2023-12-16 11:34:55 +08:00
Steven aee0e31b0a chore: update parser functions 2023-12-16 10:38:05 +08:00
Steven 47af632c79 chore: update inline parser 2023-12-16 10:09:20 +08:00
Steven 7b0ceee57b chore: update memo metadata description 2023-12-16 09:23:45 +08:00
Steven bdc867d153 fix: heading render 2023-12-16 09:12:55 +08:00
Steven 6421fbc68a chore: implement list html render 2023-12-16 09:01:19 +08:00
Steven b00443c222 chore: implement list nodes 2023-12-16 08:51:29 +08:00
Steven a10b3d3821 chore: tweak custom profile 2023-12-15 22:57:53 +08:00
Steven 7735cfac31 chore: update seed data 2023-12-15 22:34:19 +08:00
Steven 749187e1e9 chore: update dockerfile 2023-12-15 21:46:11 +08:00
Steven a9812592fe chore: tweak editor border styles 2023-12-15 21:35:31 +08:00
Steven e4070f7753 chore: bump version 2023-12-15 21:11:04 +08:00
Steven ff53187eae chore: add sitemap and robots routes 2023-12-15 20:18:01 +08:00
Steven 89ef9b8531 chore: add instance url system setting 2023-12-15 19:39:37 +08:00
Steven 56b55ad941 chore: update memo metadata 2023-12-15 19:13:56 +08:00
Steven 24672e0c5e chore: update memo metadata 2023-12-15 08:12:10 +08:00
Steven 52743017a3 chore: implement memo route 2023-12-15 07:32:49 +08:00
Steven 6cf7192d6a chore: add ssr placeholder in index.html 2023-12-14 23:29:42 +08:00
Steven 6763dab4e5 chore: handle newline in block parsers 2023-12-14 22:55:46 +08:00
Steven e0290b94b4 chore: use gomark in rss api 2023-12-14 22:33:20 +08:00
Steven 242f64fa8e chore: implement html render 2023-12-14 22:21:23 +08:00
Steven 3edce174d6 chore: remove unused methods 2023-12-14 00:24:41 +08:00
Steven 5266a62685 chore: implement html renderer 2023-12-14 00:04:20 +08:00
Steven 43ef9eaced chore: implement part of html renderer 2023-12-13 23:50:05 +08:00
Steven 453707d18c feat: implement gomark parsers 2023-12-13 21:00:13 +08:00
Steven 2d9c5d16e1 chore: fix user string 2023-12-13 19:08:06 +08:00
Steven b20e0097cf chore: implement part of nodes 2023-12-13 09:06:47 +08:00
Steven dd83782522 chore: add line break node 2023-12-12 23:38:43 +08:00
Steven aa3632e2ac chore: implement gomark skeleton 2023-12-12 23:24:02 +08:00
boojack 7f1f6f77a0 chore: update i18n with weblate (#2614)
* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-12-12 21:06:13 +08:00
Steven 7eb5be0a4e chore: fix update user 2023-12-12 20:01:31 +08:00
Steven 603a6a4971 chore: fix vacuum memo 2023-12-12 19:56:15 +08:00
Cologler 6bda64064e fix: delete one memo will delete all memos on pgsql (#2611)
fix: delete single memo will all memos on pgsql

Close #2605
2023-12-12 19:52:39 +08:00
Steven ec7992553f chore: go mod update 2023-12-11 22:21:05 +08:00
Steven e5de8c08f5 chore: clean debug code 2023-12-11 22:20:57 +08:00
Steven c608877c3e chore: clean binary entries 2023-12-11 22:16:39 +08:00
Steven 52f399a154 chore: remove unused functions 2023-12-11 21:53:16 +08:00
Gabe Cook 88728906a8 fix(copydb): fix migration to Postgres (#2601)
* chore(copydb): Use query builder during setup

* fix(copydb): Fix migration to Postgres
2023-12-11 18:05:15 +08:00
boojack 0916ec35da chore: update i18n with Weblate (#2594)
* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

* Translated using Weblate (French)

Currently translated at 100.0% (317 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/fr/

---------

Co-authored-by: Ezmana <ezmana.land@gmail.com>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
2023-12-10 15:49:29 +08:00
Steven 9f4f2e8e27 chore: fix user setting values 2023-12-10 11:57:31 +08:00
Steven 82009d3147 chore: tweak webhook section 2023-12-10 10:21:36 +08:00
Steven 0127e08a28 fix: data conflict handler 2023-12-10 10:07:26 +08:00
Steven d275713aff chore: fix timestamp type in postgres 2023-12-09 23:19:57 +08:00
Steven c50f4f4cb4 chore: update migration scripts 2023-12-09 22:18:05 +08:00
Steven fa34a7af4b chore: tweak memo parent styles 2023-12-09 19:32:16 +08:00
Steven 77b75aa6c4 chore: tweak memo display 2023-12-09 18:57:59 +08:00
Steven 9faee68dab chore: code clean 2023-12-09 18:57:18 +08:00
Steven 4f05c972d5 chore: fix jwt acl 2023-12-09 16:17:11 +08:00
Steven abda6ad041 chore: update latest schema 2023-12-09 12:05:45 +08:00
Steven 7fc7b19d64 chore: deprecate user setting legacy api 2023-12-08 22:41:47 +08:00
Steven b2d898dc15 chore: fix import order 2023-12-08 22:06:42 +08:00
Steven 15425093af chore: skip user setting key checks 2023-12-08 22:05:43 +08:00
K.B.Dharun Krishna b02aa2d5e5 chore: bump actions in workflows (#2588)
Signed-off-by: K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
2023-12-08 09:55:18 +08:00
steven c68bfcc3b9 chore: fix user setting store 2023-12-08 09:54:32 +08:00
Athurg Gooth 2964cf93ab fix: visibility of user preference is empty (#2581)
Fix visibility of user preference is empty
2023-12-07 22:50:03 +08:00
Arnaud Brochard 787cf2a9fe feat: tables support (#2573)
* Tables support

* Linter fixes

* Regex Redos fix

* Fix empty row and variables proper naming

* Default cell style

* Now unncessary

* Support rows without a starting pipe char

* Striped rows

* Fix parsing issues

* Support tabs in separators
2023-12-07 22:49:49 +08:00
Athurg Gooth ed190cd41e fix: visibility of memo editor is empty (#2580)
Fix visibility of memo editor is empty
2023-12-06 23:17:26 +08:00
Steven 33dda9bf87 chore: fix auth status checks 2023-12-06 23:03:24 +08:00
Steven fa6693a7ae chore: update list memos 2023-12-06 22:44:49 +08:00
t.yang 055a327b5e fix: detail page user-avatar size have unexpected height (#2576)
Co-authored-by: tyangs.yang <tyangs.yang@hstong.com>
2023-12-06 10:58:33 +08:00
Athurg Gooth aff1b47072 chore: remove debug log (#2582)
Remove debug log
2023-12-06 10:57:55 +08:00
Athurg Gooth 5f86769255 fix: field type of row_status for table webhook (#2579)
Fix field type of row_status for table webhook
2023-12-06 10:57:03 +08:00
Irving Ou 9c18960f47 feat: support Postgres (#2569)
* skeleton of postgres

skeleton

* Adding Postgres specific db schema sql

* user test passed

* memo store test passed

* tag is working

* update user setting test done

* activity test done

* idp test passed

* inbox test done

* memo_organizer, UNTESTED

* memo relation test passed

* webhook test passed

* system setting test passed

* passed storage test

* pass resource test

* migration_history done

* fix memo_relation_test

* fixing server memo_relation test

* passes memo relation server test

* paess memo test

* final manual testing done

* final fixes

* final fixes cleanup

* sync schema

* lint

* lint

* lint

* lint

* lint
2023-12-03 13:31:29 +08:00
Webysther Sperandio 484efbbfe2 chore: update manifest.json (#2568) 2023-12-01 16:43:48 +08:00
Steven e83d483454 refactor(frontend): use auth service 2023-12-01 09:15:02 +08:00
Steven b944418257 fix: register auth service 2023-12-01 09:13:32 +08:00
Steven 4ddd3caec7 chore: update user setting api 2023-12-01 09:03:30 +08:00
Steven c1f55abaeb chore: update user setting api 2023-11-30 23:08:54 +08:00
Steven fff42ebc0d fix: check auth status 2023-11-30 21:52:02 +08:00
Steven 2437419b7f fix: add auth status checks 2023-11-30 20:58:36 +08:00
boojack e53cedaf14 chore: update i18n with weblate (#2562)
* Translated using Weblate (Polish)

Currently translated at 46.3% (147 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pl/

* Translated using Weblate (Polish)

Currently translated at 56.1% (178 of 317 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pl/

---------

Co-authored-by: igormakarowicz <igormakarowicz@gmail.com>
2023-11-30 19:34:50 +08:00
Steven 6d469fd997 chore: fix image size 2023-11-30 19:36:12 +08:00
boojack 9552cddc93 chore: update graph format 2023-11-29 09:00:29 +08:00
boojack 34181243e5 chore: update graph route 2023-11-28 23:06:19 +08:00
boojack a0eb891132 chore: update contributor graph source 2023-11-28 22:31:34 +08:00
Steven e136355408 chore: tweak setting button style 2023-11-28 21:15:24 +08:00
Steven 5069476dcc chore: add webhook metric 2023-11-28 21:15:10 +08:00
Steven f950750d56 chore: tweak storage list title 2023-11-28 21:03:21 +08:00
Steven 0026f9e54f chore(frontend): add webhooks section 2023-11-28 20:52:48 +08:00
Steven f8f73d117b chore: update healthz message 2023-11-26 23:33:34 +08:00
Steven 8586ebf098 chore: add /healthz endpoint 2023-11-26 23:06:50 +08:00
Steven 472afce98f chore: fix current user store 2023-11-25 22:58:17 +08:00
Steven a12844f5db chore: tweak seed data 2023-11-25 10:34:54 +08:00
Steven bc965f6afa chore: implement webhook dispatch in api v1 2023-11-25 10:31:58 +08:00
Steven db95b94c9a chore: implement webhook service 2023-11-24 23:04:36 +08:00
Steven 1a5bce49c2 chore: implement webhook store 2023-11-24 22:45:38 +08:00
Steven 436eb0e591 chore: tweak s3 comments 2023-11-24 21:55:09 +08:00
Hou Xiaoxuan e016244aba fix: remove ACL when set URLPrefix (#2532) 2023-11-23 23:20:11 +08:00
Steven d317b03832 feat: add search box in resources dashboard 2023-11-23 22:12:15 +08:00
Athurg Gooth 3e138405b3 chore: remove the max height limit for single media (#2545)
Remove the max-height limit for single media
2023-11-23 09:59:33 +08:00
Steven 0dd0714ad0 chore: update security 2023-11-23 08:55:57 +08:00
Steven 45d7d0d5f6 chore: migrate get current user 2023-11-23 08:50:33 +08:00
boojack c3db4ee236 chore: translated using Weblate (Portuguese (Brazil)) (#2543)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-11-22 23:22:10 +08:00
Athurg Gooth 91296257fc chore: remove invalid access token from db (#2539)
Remove invalid access token from db
2023-11-22 23:20:45 +08:00
Steven e5f660a006 chore: migrate update user 2023-11-22 23:11:29 +08:00
Steven c0628ef95b chore: migrate create user 2023-11-22 22:58:04 +08:00
Steven c0b5070e46 chore: migrate delete user 2023-11-22 22:52:19 +08:00
Steven b1128fc786 chore: fix inline latext renderer 2023-11-22 22:38:03 +08:00
Steven bcd8a5a7a9 chore: migrate get tag suggestions 2023-11-22 22:33:02 +08:00
boojack 0cf280fa9a chore: translated using Weblate (Croatian) (#2541)
Translated using Weblate (Croatian)

Currently translated at 92.7% (293 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
2023-11-22 19:22:12 +08:00
Steven b11653658d chore: update readme 2023-11-21 20:39:48 +08:00
Cheng Jiang adf96a47bb fix: correct some Chinese translation inaccuracy (#2536)
Signed-off-by: Cheng Jiang <gabriel.chengj@gmail.com>
2023-11-21 10:58:19 +08:00
Steven 6529375a8b chore: update seed data 2023-11-19 23:58:35 +08:00
Steven e7e83874cd chore: upgrade version 2023-11-19 11:01:21 +08:00
Steven 7ef125e3af chore: update fetch tags 2023-11-19 11:01:04 +08:00
Steven dfa14689e4 chore: add click away event to date picker 2023-11-19 10:41:08 +08:00
Steven ec2995d64a chore: fix order by pinned 2023-11-19 09:42:59 +08:00
Steven 94c71cb834 chore: fix loading status 2023-11-19 09:38:04 +08:00
Steven 7f7ddf77b8 chore: update allow sign up default value 2023-11-18 12:51:07 +08:00
Steven 089cd3de87 chore: fix linter 2023-11-18 12:44:49 +08:00
zty 2d34615eac fix: parse inline latex as a inline element (#2525)
* fix:  parse inline latex as a inline element

* Update web/src/labs/marked/parser/InlineLatex.tsx

---------

Co-authored-by: zty <zty.dev@outlook.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-11-18 12:41:33 +08:00
Steven 4da3c1d5e5 chore: fix update user 2023-11-18 12:37:24 +08:00
zty 4f222bca5c fix: keep content and query param on save when access token is invalid (#2524)
fix:
keep content on save when access token is invalid

Co-authored-by: zty <zty.dev@outlook.com>
2023-11-17 10:01:14 +08:00
Steven 0bb0407f46 chore: add overflow tips to tag 2023-11-17 08:22:47 +08:00
Zexi 8bc117bce9 feat: optimize media resource display (#2518)
* feat: optimize media resource display

* fix: type error

* Update web/src/components/MemoResourceListView.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update MemoResourceListView.tsx

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-11-17 08:03:26 +08:00
Athurg Gooth afd0e72e37 chore: skip timeout for blob upload (#2516)
Skip timeout for blob upload
2023-11-15 17:23:56 +08:00
Vespa314 d758ba2702 fix: allow host role update user info (#2515) 2023-11-15 11:43:49 +08:00
Leyang 0f126ec217 docs: add obsidian plugin (#2512) 2023-11-14 23:22:54 +08:00
Steven c1a6dc9bac chore: fix home sidebar max width 2023-11-14 23:23:05 +08:00
Athurg Gooth 6ee95a2c0c fix: clear localStorage while draft is empty (#2510)
* Clear localStorage while draft is empty

* change == into ===
2023-11-14 10:02:16 +08:00
Athurg Gooth 6814915c88 feat: backup file rotate (#2511)
Add support for rotate backup files
2023-11-13 22:12:25 +08:00
Athurg Gooth 52fdf8bccd fix: persist jwt expires by cookie (#2509)
fix pesist jwt expires by cookie
2023-11-13 13:52:04 +08:00
Mahoo Huang f67757f606 feat: add editor auto focus preference (#2498)
* feat: add editor auto focus perference

* feat: set editor auto focus
2023-11-13 13:51:52 +08:00
ti777777 38f05fd6f2 chore: fix tag in http_getter.go (#2500)
Update http_getter.go

fix tag in  http_getter.go
2023-11-11 23:21:15 +08:00
Vespa314 65022beb0d fix: duplicate memo filter in user profile page (#2502) 2023-11-11 23:20:53 +08:00
swebdev 5d81338aca fix: demo banner link for self-hosting guide (#2499) 2023-11-11 19:15:24 +08:00
Steven c288d49138 chore: fix decouple user name 2023-11-10 23:08:11 +08:00
Steven 0ea0645258 chore: add use reponsive width 2023-11-10 11:22:32 +08:00
steven 9227ca5b5b chore: update debounce ms 2023-11-09 08:52:02 +08:00
steven eb6b0ddead chore: update navigation 2023-11-09 08:46:26 +08:00
Steven dca90fb5d2 chore: update header 2023-11-09 08:27:46 +08:00
steven 172e27016b chore: upgrade frontend deps 2023-11-09 08:26:00 +08:00
steven 6da2ff7ffb chore: clean logs 2023-11-09 08:25:28 +08:00
Steven 6c433b452f chore: update user checks 2023-11-08 22:58:35 +08:00
Steven 65a34ee41a chore: update home sidebar 2023-11-08 22:18:12 +08:00
Steven 5ff0234c71 chore: update response styles 2023-11-08 22:10:15 +08:00
Steven e76509a577 chore: update header menu style in mobile view 2023-11-08 22:00:49 +08:00
Steven 4499f45b67 chore: deprecate daily review offset local setting 2023-11-08 21:49:03 +08:00
boojack 504d1768f2 chore: update i18n with Weblate (#2492)
* Translated using Weblate (Chinese (Traditional))

Currently translated at 91.7% (290 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

---------

Co-authored-by: dwong33 <dwong@posteo.ch>
2023-11-08 13:02:24 +08:00
zty caea065594 feat: add share btn in more-action (#2491)
Co-authored-by: zty <zty.dev@outlook.com>
2023-11-08 10:34:07 +08:00
Athurg Gooth 2ee426386a fix: skip system_setting check while copydb (#2490)
Skip system_setting check while copydb
2023-11-08 10:06:27 +08:00
boojack 9df05fe0fa chore: update i18n from Weblate (#2489)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-11-07 22:39:27 +08:00
zty 184f79ef8e feat: support code in headings (#2488)
Co-authored-by: zty <zty.dev@outlook.com>
2023-11-07 22:38:38 +08:00
Athurg Gooth 35f0861d6e fix: prevent copydb to create a fresh memos (#2486)
Prevent copydb to create a fresh memos
2023-11-07 13:53:53 +08:00
Steven c4d27e7a78 chore: update backend dependencies 2023-11-07 07:36:16 +08:00
Steven 7e545533cf chore: update resource cache control 2023-11-07 07:24:41 +08:00
Steven 32cafbff9b chore: add OverflowTip kit component 2023-11-07 07:20:17 +08:00
Steven 9c4f72c96e chore: update tooltips 2023-11-07 07:06:38 +08:00
Steven 5e4493b227 chore: remove debug codes 2023-11-06 23:20:26 +08:00
Steven 834b58fbbd feat: add version update inbox message 2023-11-06 22:53:55 +08:00
Steven 342d1aeefb fix: version checker 2023-11-06 22:33:12 +08:00
Steven 363c107359 chore: update frontend deps 2023-11-06 21:08:09 +08:00
boojack 0458269e15 revert: "chore: add frontend type definitions" (#2483)
Revert "chore: add frontend type definitions (#2482)"

This reverts commit 64d4db81ca.
2023-11-06 21:01:17 +08:00
boojack 64d4db81ca chore: add frontend type definitions (#2482)
chore: update
2023-11-06 21:00:42 +08:00
Steven 865cc997a4 chore: remove upgrade version banner 2023-11-06 20:51:59 +08:00
Steven 981bfe0464 feat: add version checker 2023-11-06 20:49:02 +08:00
Steven 695fb1e0ca chore: update migration history store 2023-11-06 08:33:31 +08:00
Steven 21ad6cc871 chore: update tag service creator 2023-11-06 08:05:07 +08:00
Steven c24181b2be chore: fix jwt checks 2023-11-05 23:39:30 +08:00
Steven 39a0e69b04 chore: update function name 2023-11-05 23:28:09 +08:00
Steven e60e47f76f chore: update user definition 2023-11-05 23:03:43 +08:00
Steven e67820cabe chore: update list user api permission 2023-11-05 22:35:09 +08:00
Steven 3266c3a58a chore: update link styles 2023-11-05 22:26:09 +08:00
Steven ef820a1138 chore: fix memo editor padding in daily review 2023-11-05 21:42:02 +08:00
Steven 137e64b0dd chore: update metrics 2023-11-05 21:41:47 +08:00
Steven 982b0285c9 chore: fix date picker 2023-11-05 16:02:51 +08:00
Steven 405fc2b4d2 chore: simplify find migration history 2023-11-05 15:49:57 +08:00
Steven eacd3e1c17 chore: fix mysql latest schema 2023-11-05 15:38:45 +08:00
Christopher a62f1e15a6 fix: private memos being public (#2480)
* fix(web/memo): filter out public option

Filter out the public option if we have disabled public memos

* feat(api/memo): sanity check for disabled public memos

In case something goes wrong, we check the system setting on the backend in order to valdiate if we can create a public memo

* refactor(web/memo): disable public option

Seems like a better option than removing it, as it looks werid if you are looking at a memo that is previously public

* fix(web/memo): use translation keys

* chore(web/editor): remove unsused tooltip

* revert(api/memo): sanity check

* fix(web/memo): allow admins to create public memos

* chore(web/memo): remove unused import

* fix(web/memo): check for both host and admin

* fix(web/memo): remove warning text from MemoDetail
2023-11-05 01:19:54 +08:00
Zexi 8b0083ffc5 fix: auto fetch more (#2472)
* fix: auto fetch more

* feat: use union type
2023-11-03 05:16:55 +08:00
Athurg Gooth 5d69d89627 feat: week from monday in heatmap for zh-Hans and ko (#2457)
* week from monday in heatmap for zh-Hans and ko

* optimize code
2023-10-31 12:06:14 +08:00
Athurg Gooth b966c16dd5 fix: data too large for mysql (#2470)
* Extend some TEXT field to LONGTEXT in mysql

* move db migration version

* fix error in migrate SQL
2023-10-31 10:23:15 +08:00
Steven 97190645cc chore: update memo editor styles 2023-10-29 23:59:23 +08:00
Steven c26417de70 chore: update docs links 2023-10-29 18:36:09 +08:00
Steven f5c1e79195 chore: update about dialog 2023-10-28 15:17:33 +08:00
Steven d02105ca30 chore: update i18n 2023-10-28 15:10:20 +08:00
Steven 44e50797ca chore: update go mods 2023-10-28 14:57:39 +08:00
Steven 7058f0c8c2 chore: add docs link in settings 2023-10-28 14:56:08 +08:00
Steven f532ccdf94 chore: upgrade frontend deps 2023-10-28 14:55:57 +08:00
Steven a6fcdfce05 chore: update memo comment i18n 2023-10-28 11:39:10 +08:00
Steven dca712d273 chore: fix resource tests 2023-10-28 10:51:03 +08:00
Steven ac81d856f6 chore: delete resource file sync 2023-10-28 10:42:39 +08:00
Steven 88fb79e458 chore: impl inbox store for mysql 2023-10-28 09:44:52 +08:00
Steven 480c53d7a2 chore: fix id converter 2023-10-28 09:04:32 +08:00
Steven 2b7d7c95a5 chore: update inbox detect 2023-10-28 09:02:02 +08:00
Steven 0ee938c38b chore: remove unused inbox status 2023-10-28 02:49:35 +08:00
Steven 3c36cc2953 feat: add inbox ui 2023-10-28 02:43:46 +08:00
Steven 79bb3253b6 chore: add activity service 2023-10-28 00:21:53 +08:00
Steven 18107248aa chore: rename list inbox 2023-10-28 00:08:42 +08:00
Athurg Gooth 4f1bb55e55 fix: metric env not affect (#2450)
fix metric env not affect
2023-10-27 23:26:23 +08:00
Athurg Gooth 20d3abb99a chore: downgrade log level for auto backup disable (#2454)
downgrade log level for auto backup disable
2023-10-27 23:25:51 +08:00
Steven 1b34119e60 chore: update activity store definition 2023-10-27 23:24:56 +08:00
Steven 9d2b785be6 chore: fix inbox test 2023-10-27 23:17:17 +08:00
Steven 36b4ba33fa chore: remove outdated activity definition 2023-10-27 23:11:56 +08:00
Steven 625ebbea1a chore: update proto linter action 2023-10-27 21:49:07 +08:00
Athurg Gooth 0f4e5857f0 chore: remove gRPC listener (#2456)
Disable gRPC listener
2023-10-27 21:38:17 +08:00
Athurg Gooth 76d955a69a chore: docker compose dev (#2458)
* add golang build cache volume to speedup build

* replace `lint` with `npm` to run more scripts

* wrap golangci-lint as entrypoint instead of command
2023-10-27 21:21:52 +08:00
Athurg Gooth e41ea445c9 fix: missing relation after post comment (#2452)
fix missing relation after post comment
2023-10-27 10:12:25 +08:00
boojack c952651dc1 chore: update i18n from Weblate (#2455)
* Translated using Weblate (Croatian)

Currently translated at 92.3% (290 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

* Translated using Weblate (Korean)

Currently translated at 100.0% (314 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

---------

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
Co-authored-by: nulta <un5450@naver.com>
2023-10-27 10:12:02 +08:00
Steven 58e771a1d7 chore: combine v2 services 2023-10-27 09:07:35 +08:00
Steven e876ed3717 feat: impl part of inbox service 2023-10-27 09:01:17 +08:00
Steven 67d2e4ebcb chore: update method name 2023-10-27 08:36:43 +08:00
Steven 4ea78fa1a2 chore: impl inbox store methods 2023-10-27 08:17:58 +08:00
Steven 93b8e2211c chore: update dev latest schema 2023-10-27 01:18:00 +08:00
Steven 052216c471 chore: fix list activities typo 2023-10-27 01:11:41 +08:00
Steven e5978a70f5 chore: initial inbox store model 2023-10-27 01:10:19 +08:00
Steven 59f0ee862d chore: fix viper default value 2023-10-27 00:49:58 +08:00
Athurg Gooth 215981dfde chore: remote context.Context pointer (#2448)
remote context.Context pointer
2023-10-26 20:21:44 +08:00
Athurg Gooth bfdb33f26b chore: add a flag to change metric switch (#2447)
* add a flag to change metric switch

* change the default value of metric
2023-10-26 20:21:18 +08:00
Steven 5b3af827e1 chore: move common packages to internal 2023-10-26 09:02:50 +08:00
Steven 9859d77cba chore: update links 2023-10-26 09:00:36 +08:00
Athurg Gooth 064c930aed fix: validate username before create token (#2439)
Validate username before create token
2023-10-25 12:05:44 +08:00
Athurg Gooth 043357d7dc fix: list token for others failed (#2440)
Fix list token for others failed
2023-10-25 12:05:30 +08:00
Athurg Gooth 3a5deefe11 chore: disable NPM update notice while running lint (#2438)
Disable NPM update notice while running lint
2023-10-25 10:00:45 +08:00
Athurg Gooth 2c71371b29 chore: update @typescript-eslint to avoid WARNING (#2437)
Update @typescript-eslint to avoid WARNING
2023-10-25 10:00:30 +08:00
Steven 222e6b28b7 chore: update website links in readme 2023-10-25 07:43:52 +08:00
Athurg Gooth 496cde87b2 feat: list access tokens by admin (#2434)
* Allow admin user list access_tokens of anyone

* fix undefined variable

* Update api/v2/user_service.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-10-24 18:51:01 +08:00
Athurg Gooth 79bbe4b82a feat: support filter creator in /api/v2/memos (#2432)
* Add creator_id param in /api/v2/memos

* make creator_id optional
2023-10-23 21:32:58 +08:00
Zexi 035d71e07c fix: visibility translation (#2429)
* fix: visibility translation

* refactor: remove useless file

* feat: add visibility icon
2023-10-23 08:06:59 +08:00
Christopher 82effea070 tweak(web): use iconbutton for editor helpers (#2426) 2023-10-22 22:10:27 +08:00
Lincoln Nogueira 331f4dcc1b chore: update dev scripts (#2427)
- add type-gen
- remove some unused air settings
- restrict air monitoring to changed go files
2023-10-22 22:09:25 +08:00
Lincoln Nogueira 055b246857 chore: update ci (#2428)
- restrict codeql and backend tests from running on pull requests with unrelated files
- upgrade codeql: current version is generating a deprecation warning in logs
2023-10-22 22:08:38 +08:00
boojack 8fc9a318a4 chore: translated using Weblate (Portuguese (Brazil)) (#2422)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (314 of 314 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
2023-10-22 12:27:29 +08:00
MotH 9aed80a4fd feat: better tag suggestion (#2421)
Better Tag Suggestion
2023-10-22 09:15:25 +08:00
MotH c31f306b5b fix: smaller logo file (#2418) 2023-10-22 05:51:37 +08:00
Steven bfd2dbfee2 chore: fix update resource api 2023-10-21 12:41:55 +08:00
Steven c42af95dd3 chore: fix update user 2023-10-21 12:22:23 +08:00
Steven 89a073adc0 chore: implement create user api v2 2023-10-21 12:19:06 +08:00
Steven 1c2d82a62f chore: remove major label 2023-10-21 09:36:50 +08:00
Steven 02f7a36fa4 chore: remove unsupported linux/arm/v7 2023-10-21 08:29:21 +08:00
Steven a76f762196 chore: update memo share dialog 2023-10-21 08:19:25 +08:00
Steven 2c2955a229 chore: add back linux/arm/v7 2023-10-21 08:15:25 +08:00
Steven d06d01cef2 chore: release mysql driver 2023-10-21 01:25:07 +08:00
boojack 4b91738f21 chore: translated using Weblate (Croatian) (#2413)
Translated using Weblate (Croatian)

Currently translated at 87.5% (274 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

Co-authored-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
2023-10-21 01:23:12 +08:00
Steven 12fd8f34be chore: fix styles 2023-10-21 01:23:21 +08:00
Steven c2ab05d422 chore: fix member section style 2023-10-21 01:09:52 +08:00
Steven 7b25b8c1e1 feat: update daily review 2023-10-21 00:57:44 +08:00
Athurg Gooth af7c0a76d0 fix: fail to update user's update_ts (#2410) 2023-10-20 19:10:38 +08:00
Athurg Gooth 664c9c4a7c chore: extend height of setting page (#2407)
Extend height of setting page
2023-10-20 17:41:37 +08:00
Athurg Gooth fd5d51ee54 fix: some fields of profile leaked without auth (#2408)
* fix some fields of profile leaked without auth

* protect driver and dsn of profile
2023-10-20 17:41:21 +08:00
Steven 1b105db958 chore: fix field syntax 2023-10-20 08:52:16 +08:00
Steven a541e8d3e3 chore: upgrade version 2023-10-20 08:49:58 +08:00
Steven 6f2ca6c87a chore: update find memo api 2023-10-20 08:48:52 +08:00
Steven 952539f817 chore: update memo editor dialog 2023-10-20 08:19:08 +08:00
Steven c87b679f41 chore: add memo relation list 2023-10-19 21:26:38 +08:00
Baksi e6b20c5246 chore: update Shortcuts link (#2405)
* Update Shortcuts

* Update README.md

* Update README.md
2023-10-19 04:56:59 -05:00
Athurg Gooth 0bfcff676c feat: add support for remember sign in (#2402) 2023-10-18 20:38:49 -05:00
Athurg Gooth 37601e5d03 chore: change the timeout value of golangci-lint (#2403) 2023-10-18 20:37:35 -05:00
Steven 21c70e7993 feat: update memo relations dialog 2023-10-19 00:18:07 +08:00
Athurg Gooth 22d331d6c4 chore: switch storage of selected date in DailyReview (#2399)
Switch storage of selected date in DailyReview
2023-10-18 09:06:34 -05:00
Steven 9bfb2d60b9 chore: tweak wording 2023-10-18 06:05:19 +08:00
Steven 203b2d9181 chore: fix container styles 2023-10-18 06:02:39 +08:00
boojack ddc4566dcb chore: translated using Weblate (German) (#2396)
Translated using Weblate (German)

Currently translated at 99.6% (312 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

Co-authored-by: Frank Emmerlich <femmdi2012@gmail.com>
2023-10-17 10:49:36 -05:00
Steven 1755c9dc79 chore: update button style 2023-10-17 23:49:26 +08:00
Steven a5df36eff2 chore: update metrics 2023-10-17 23:44:16 +08:00
Athurg Gooth e30d0c2dd0 fix: image width error while loading (#2394)
fix image width error while loading
2023-10-17 09:00:45 -05:00
boojack 213c2ea71b chore: translated with Weblate (German) (#2390)
Translated using Weblate (German)

Currently translated at 99.6% (312 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

Co-authored-by: Frank Emmerlich <femmdi2012@gmail.com>
2023-10-16 11:21:11 -05:00
guopeng 73f59eaf09 fix: storage setting changed don't take effect (#2385)
* fix: Storage setting changed don't take effect

* fix: Storage setting changed don't take effect

* fix: Storage setting changed don't take effect
2023-10-16 08:07:21 -05:00
TianLun Song c999d71455 chore: update iOS shortcut link (#2387)
* Update README.md

New shortcut for memos version 0.15.0 and above on IOS

* Update README.md

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-10-16 08:06:36 -05:00
Steven 5359d5a66d chore: add container-queries tailwind plugin 2023-10-14 14:13:55 +08:00
Steven c58820fa64 chore: update username regexp 2023-10-14 13:42:27 +08:00
Steven cfc5599334 chore: cleanup less files 2023-10-14 12:06:24 +08:00
Steven c02f3c0a7d chore: remove less files in editor 2023-10-14 11:55:37 +08:00
Steven dd83358850 chore: update some styles 2023-10-14 01:12:41 +08:00
Steven d95a6ce898 chore: add ar locale item 2023-10-14 00:25:01 +08:00
boojack 7e80e14f16 chore: add Arabic from weblate (#2382)
* Added translation using Weblate (Arabic)

* Translated using Weblate (Arabic)

Currently translated at 46.6% (146 of 313 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ar/

---------

Co-authored-by: Ali AlShaikh <Mi3LiX9@outlook.sa>
2023-10-13 11:11:56 -05:00
Steven 219304e38d chore: update frontend deps 2023-10-13 23:29:55 +08:00
Steven 20e5597104 chore: fix memo container max width 2023-10-13 23:26:56 +08:00
Athurg Gooth ed2e299797 fix: invalid type convert in apiv2 (#2380)
fix invalid type convert in apiv2
2023-10-13 09:53:58 -05:00
boojack bacc529391 chore: fix linter errors (#2381)
* chore: fix linter errors

* chore: update

* chore: update
2023-10-13 09:53:02 -05:00
Steven ed1ff11e80 chore: update 2023-10-13 00:13:13 +08:00
Steven a0f8e6987c chore: update go deps 2023-10-13 00:08:52 +08:00
Athurg Gooth d3e32f0d5a chore: add latency in log (#2374)
* Print profile.Data in boot log

* Add latency in request log
2023-10-10 06:03:32 -05:00
Athurg Gooth 95bfcb8055 chore: print profile.Data in boot log (#2373)
Print profile.Data in boot log
2023-10-10 05:59:19 -05:00
Athurg Gooth 096c489eb3 feat: copy data between drivers (#2370)
* Add copydb command to copy data between drivers

* Check if table is empty before copy
2023-10-09 22:45:17 -05:00
boojack b6425f9004 chore: update i18n with weblate (#2369)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Qing Long <longyinx@duck.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
2023-10-09 10:54:54 -05:00
Steven ab2c86640b chore: move rate limiter to apiv1 2023-10-09 23:10:41 +08:00
Steven 1489feb054 chore: update common dialog default color 2023-10-09 23:08:52 +08:00
Steven acdeabb861 chore: add issue template config.yml 2023-10-09 22:10:28 +08:00
Athurg Gooth 6bb6c043e5 feat: add support for ListMemoOrganizer (#2367)
* Add support for ListMemoOrganizer

* fix rows not close
2023-10-09 08:18:47 -05:00
Athurg Gooth fa2bba51c1 feat: add support for ListActivity (#2365)
Add support for ListActivity
2023-10-09 08:18:33 -05:00
Steven 3822c26e32 chore: update memo props 2023-10-09 21:09:17 +08:00
Athurg Gooth 425b43b3bb fix: ListTag not support omit params (#2366)
fix ListTag not support omit params
2023-10-09 01:40:54 -05:00
Athurg Gooth c00dac1bbf fix: index page failed with 429 (#2363) 2023-10-08 20:54:12 -05:00
Steven 3ff4d19782 chore: update initial global loader 2023-10-08 20:31:38 +08:00
Steven 31997936d6 chore: move resource public api 2023-10-08 19:40:30 +08:00
Athurg Gooth 287f1beb90 fix: create storage without some attributes (#2358) 2023-10-08 05:30:24 -05:00
Athurg Gooth 7680be1a2f fix: create user without some attributes (#2357) 2023-10-08 05:29:32 -05:00
Athurg Gooth 55e0fbf24e fix: create activity without some attributes (#2356) 2023-10-08 05:29:22 -05:00
Athurg Gooth eaac17a236 fix: create memo without some attributes (#2355) 2023-10-08 05:29:12 -05:00
Athurg Gooth 1fbd568dfe fix: create resource without some attributes (#2354) 2023-10-08 05:29:03 -05:00
Athurg Gooth c0619ef4a4 fix: CreateIdentityProvider without id (#2352) 2023-10-08 05:28:22 -05:00
Athurg Gooth b2aa66b4fd fix: migration always in mysql (#2353) 2023-10-08 05:28:11 -05:00
boojack dfaf2ee29c chore: update pnpm scripts (#2350)
* chore: update pnpm scripts

* chore: update development guide
2023-10-07 12:06:18 -05:00
Steven b938c8d7b6 chore: only show comments in memo detail page 2023-10-08 00:42:02 +08:00
Steven 553de3cc7e fix: mysql syntax 2023-10-07 22:56:12 +08:00
Steven 73980e9644 chore: fix video element syntax 2023-10-07 22:01:07 +08:00
Athurg Gooth 087e631dd8 chore: optmize docker-compose.dev.yml (#2347)
Optmize docker-compose.dev.yml
2023-10-07 08:24:53 -05:00
boojack 76fb280720 chore: translated with Weblate (#2348)
Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

Co-authored-by: Qing Long <longyinx@duck.com>
2023-10-07 08:23:06 -05:00
Steven 6ffc09d86a chore: remove unused httpmeta getter api 2023-10-06 23:03:36 +08:00
白宦成 125c9c92eb chore: compress image and reduce 500kb in network (#2339)
feat: compress image and reduce 500kb in network
2023-10-06 07:45:17 -05:00
Steven 15eb95f964 chore: delete resource file synchronously 2023-10-06 19:02:40 +08:00
boojack ed96d65645 chore: update i18n with weblate (#2338)
* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@users.noreply.github.com>
Co-authored-by: Qing Long <longyinx@duck.com>
2023-10-06 05:29:50 -05:00
boojack 9c2f87ec2e chore: update i18n with weblate (#2337)
* Translated using Weblate (English)

Currently translated at 100.0% (315 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 98.4% (310 of 315 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

---------

Co-authored-by: Lincoln Nogueira <lincolnthalles@gmail.com>
2023-10-05 22:49:38 -05:00
Steven 19f6ed5530 chore: remove pr preview actions 2023-10-06 11:00:17 +08:00
Steven 57c5a92427 chore: update archived memo styles 2023-10-06 00:34:40 +08:00
Steven 9410570195 chore: update version 2023-10-06 00:34:38 +08:00
Steven c0422dea5b chore: fix sqlite migrator 2023-10-06 00:34:06 +08:00
Steven 7791fb10d8 chore: update new db driver 2023-10-05 23:19:52 +08:00
Steven a6ee61e96d chore: update package name 2023-10-05 23:11:29 +08:00
boojack 99d9bd2d75 chore: update i18n with weblate (#2333)
* Translated using Weblate (Dutch)

Currently translated at 85.7% (271 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 85.4% (270 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/pt_BR/

* Translated using Weblate (German)

Currently translated at 88.9% (281 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/de/

* Translated using Weblate (Russian)

Currently translated at 86.7% (274 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ru/

* Translated using Weblate (Japanese)

Currently translated at 90.8% (287 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ja/

* Translated using Weblate (Croatian)

Currently translated at 86.3% (273 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hr/

* Translated using Weblate (Hindi)

Currently translated at 68.0% (215 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/hi/

* Translated using Weblate (Italian)

Currently translated at 89.2% (282 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/it/

* Translated using Weblate (Korean)

Currently translated at 89.2% (282 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/ko/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 90.8% (287 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hant/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 89.8% (284 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/zh_Hans/

* Translated using Weblate (English)

Currently translated at 100.0% (316 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/en/

---------

Co-authored-by: Jasper Platenburg <jasperdgp@outlook.com>
Co-authored-by: memos <usememos@gmail.com>
2023-10-05 08:36:23 -05:00
boojack e7aeca736b chore: update i18n with weblate (#2332)
* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/

* Translated using Weblate (Dutch)

Currently translated at 77.8% (246 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 78.4% (248 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 78.7% (249 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 79.1% (250 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 79.7% (252 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

* Translated using Weblate (Dutch)

Currently translated at 81.6% (258 of 316 strings)

Translation: memos-i18n/i18n
Translate-URL: https://hosted.weblate.org/projects/memos-i18n/english/nl/

---------

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Jasper Platenburg <jasperdgp@outlook.com>
2023-10-05 04:36:00 -05:00
Steven e85f325eb2 chore: add tranlated status badge 2023-10-05 17:32:23 +08:00
Steven 7dcc5cbaf1 chore: fix mysql migrator 2023-10-05 17:11:28 +08:00
Steven 1cdd70e008 chore: update dark mode styles 2023-10-05 16:16:02 +08:00
Steven 6a11fc571d chore: update empty icon 2023-10-05 15:52:16 +08:00
Steven 771fe394fd chore: fix initial guide 2023-10-05 15:50:16 +08:00
Steven d474d1abd0 chore: update store cache 2023-10-05 15:17:40 +08:00
Steven 576111741b chore: downgrade zustand 2023-10-05 15:13:02 +08:00
Steven 9ac44dfbd9 chore: update mui/joy version 2023-10-05 15:08:55 +08:00
Steven 110b53b899 chore: update frontend deps 2023-10-05 15:07:10 +08:00
Steven 42e8d51550 chore: update i18n 2023-10-05 15:07:03 +08:00
Steven fd7043ea40 chore: fix editor cache 2023-10-05 14:20:35 +08:00
Steven 34ae9b0687 chore: update default storage back to database 2023-10-05 13:36:33 +08:00
Steven 077bf95425 chore: add pinned icon in status bar 2023-10-05 13:12:03 +08:00
Steven e465b2f0e8 chore: update i18n for auth pages 2023-10-05 12:48:40 +08:00
Steven 01ff3f73f8 chore: update auth pages 2023-10-05 12:38:46 +08:00
Steven 8aae0d00cd chore: fix fetch comments 2023-10-05 08:58:44 +08:00
Steven 16dad8b00d chore: update logo 2023-10-05 08:40:25 +08:00
Steven 7dc4bc5714 chore: update resource service 2023-10-03 23:44:14 +08:00
K.B.Dharun Krishna 2e82ba50f2 chore: bump actions/checkout; actions/setup-go to v4 (#2325)
* chore: bump actions/checkout to v4

Signed-off-by: GitHub <noreply@github.com>

* chore: bump actions/setup-go to v4

Signed-off-by: GitHub <noreply@github.com>

---------

Signed-off-by: GitHub <noreply@github.com>
2023-10-03 16:58:47 +08:00
Steven 1542f3172a chore: update tag service 2023-10-03 09:39:39 +08:00
serverless83 69d575fd5b chore: update it.json translation (#2323)
Changed translation of "private" to "Privato" instead of "Privao" (missing the letter "t")

Signed-off-by: serverless83 <35410475+serverless83@users.noreply.github.com>
2023-10-02 20:01:16 -05:00
Steven 607fecf437 chore: update store tests 2023-10-03 00:47:34 +08:00
Steven 91f7839b31 chore: update memo detail styles 2023-10-03 00:25:22 +08:00
Steven 078bc164d5 chore: update memo relations view 2023-10-02 08:26:15 +08:00
Steven 70f464e6f2 chore: update frontend deps 2023-10-01 22:14:33 +08:00
Steven e40621eb0f chore: implement memo content views 2023-10-01 22:14:25 +08:00
Steven fd395e5661 chore: update list memo relations 2023-10-01 21:35:17 +08:00
Steven be046cae8e chore: add parent field to memo 2023-10-01 16:27:40 +08:00
Steven 922de07751 feat: impl memo comment api 2023-10-01 14:44:10 +08:00
Steven 7549c807ac chore: update memo view activity 2023-10-01 14:14:33 +08:00
Steven de5eccf9d6 chore: update icon styles 2023-09-30 02:06:30 +08:00
Steven 952225d1da chore: add back to top button 2023-09-30 02:04:13 +08:00
steven a928c4f845 chore: update error format 2023-09-29 13:04:54 +08:00
Johan 73e189ea61 chore: update fr.json (#2304)
* Update fr.json

Updated some translations

Signed-off-by: Johan <45337552+LittleJ@users.noreply.github.com>

* Apply suggestions from code review

Signed-off-by: boojack <stevenlgtm@gmail.com>

---------

Signed-off-by: Johan <45337552+LittleJ@users.noreply.github.com>
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-29 04:51:14 +00:00
steven 8168fb71a8 chore: update migrator 2023-09-29 12:47:49 +08:00
Steven 87ddeb2c79 chore: adjust store test for mysql 2023-09-29 09:15:54 +08:00
Athurg Gooth 255254eb69 feat: add some dev tools in the docker compose (#2309)
* Add some dev tools in the docker compose

* Merge tsc and lint
2023-09-28 14:54:11 +00:00
Athurg Gooth c72f221fc0 feat: support mysql as backend storage driver (#2300)
* Rename checkDSN to checkDataDir

* Add option to set DSN and db driver

* Add mysql driver skeleton

* Add mysql container in compose for debug

* Add basic function for mysql driver

* Cleanup go mod with tidy

* Cleanup go.sum with tidy

* Add DeleteUser support for mysql driver

* Fix UpdateUser of mysql driver

* Add DeleteTag support for mysql driver

* Add DeleteResource support for mysql driver

* Add UpdateMemo and DeleteMemo support for mysql driver

* Add MemoRelation support for mysql driver

* Add MemoOrganizer support for mysql driver

* Add Idp support for mysql driver

* Add Storage support for mysql driver

* Add FindMemosVisibilityList support for mysql driver

* Add Vacuum support for mysql driver

* Add Migration support for mysql driver

* Add Migration support for mysql driver

* Fix ListMemo failed with referece

* Change Activity.CreateTs type in MySQL

* Change User.CreateTs type in MySQL

* Fix by golangci-lint

* Change Resource.CreateTs type in MySQL

* Change MigrationHistory.CreateTs type in MySQL

* Change Memo.CreateTs type in MySQL
2023-09-28 09:09:52 -05:00
CorrectRoadH 4ca2b551f5 chore: update seed data (#2311) 2023-09-28 09:03:32 -05:00
Athurg Gooth 5b6b2f0528 fix: apiv2 failed in container (#2307) 2023-09-28 05:45:45 -05:00
Steven fbbfb11916 chore: adjust memo elements 2023-09-28 08:59:55 +08:00
Steven c54febd024 chore: fix reset script 2023-09-27 18:55:26 +08:00
Athurg Gooth 5ebf920a61 chore: stop process on build error (#2295)
* Move migration and seed code into driver

* Stop process on build error
2023-09-27 11:56:39 +08:00
Athurg Gooth 5121e9f954 chore: move migration and seed code into driver (#2294)
Move migration and seed code into driver
2023-09-27 11:56:20 +08:00
Athurg Gooth ca98367a0a chore: store vacuum and clean (#2293)
* Move all vacuum code into driver

* Remove db from Store
2023-09-26 20:27:31 -05:00
Steven 9abf294eed chore: update seed data 2023-09-27 09:13:56 +08:00
Athurg Gooth 9ce22e849c chore: move SQL code of Memo into Driver (#2292) 2023-09-27 00:57:12 +00:00
Athurg Gooth 58b84f83d1 chore: move SQL code of MemoOrganizer into Driver (#2291) 2023-09-26 19:54:50 -05:00
Athurg Gooth acbde4fb2d chore: move SQL code of MemoRelation into Driver (#2290) 2023-09-26 19:43:46 -05:00
Steven 53090a7273 chore: show unused resources in dashboard 2023-09-27 08:09:30 +08:00
Steven 71ee299de7 chore: drop shortcut 2023-09-27 07:28:17 +08:00
Steven 9d1c9fc505 chore: regenerate swagger docs 2023-09-27 00:52:42 +08:00
Steven 03a0972712 chore: rename sqlite entry file name 2023-09-27 00:51:16 +08:00
Steven 0bddbba00e chore: fix frontend linter 2023-09-27 00:45:15 +08:00
Steven 6007f48b7d chore: retire memo resource relation table 2023-09-27 00:40:16 +08:00
Steven 4f10198ec0 chore: add tooltip to icon buttons 2023-09-26 23:48:34 +08:00
Steven 7722c41680 chore: add edit button to memo detail page 2023-09-26 23:46:58 +08:00
Steven 7cdc5c711c chore: update key of daily memo 2023-09-26 23:34:35 +08:00
Steven 4180cc3a3d refactor: migrate storage to driver 2023-09-26 19:43:55 +08:00
Steven d6789550a0 refactor: migrate tag to driver 2023-09-26 19:37:22 +08:00
Steven d68da34eec refactor: migrate idp to driver 2023-09-26 19:17:17 +08:00
Steven 63b55c4f65 chore: fix tests 2023-09-26 19:15:18 +08:00
Steven 96395b6d75 chore: rename package sqlite3 to sqlite 2023-09-26 19:07:14 +08:00
Athurg Gooth d3a6fa50d6 chore: move sql code of Resource into driver (#2286)
Move sql code of Resource into driver
2023-09-26 19:04:07 +08:00
May Kittens Devour Your Soul 47f22a20ba chore: update Croatian (#2283)
* Add files via upload

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Update hr.json

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Update hr.json

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>

* Delete web/src/css/prism.css

Signed-off-by: boojack <stevenlgtm@gmail.com>

---------

Signed-off-by: May Kittens Devour Your Soul <yoshimitsu002@gmail.com>
Signed-off-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-26 19:03:50 +08:00
Athurg Gooth 14ec524805 chore: move sql code of UserSetting into Driver (#2282)
* Move SQL code of UserSetting into Driver

* Fix golang import issue
2023-09-26 19:02:48 +08:00
Athurg Gooth fcba3ffa26 chore: move sql code of User into driver (#2281)
Move SQL code of User into Driver
2023-09-26 18:23:45 +08:00
Athurg Gooth 41eba71f0f chore: split sql to driver (#2279)
* Add new database interface for SQL operations

* Move SQL code of Activity into Database

* Rename `Database` into `Driver`

* Move SQL code of SystemSetting into Driver

* Fix store.New in text code

* Change database into driver in the variables

* Change sqlite3.New into sqlite3.NewDriver
2023-09-26 17:16:58 +08:00
Steven 85ed0202d8 chore: fix user request cache 2023-09-25 20:52:29 +08:00
Steven 745902e8b1 chore: update access token order 2023-09-25 20:14:01 +08:00
Steven ad3487a9ac chore: update username matcher 2023-09-25 20:03:58 +08:00
Steven 8c2f89edc5 chore: update demo username 2023-09-25 09:10:39 +08:00
Steven 6cff920f0c chore: update user demo data 2023-09-23 20:41:47 +08:00
Steven 27f3f6fbf0 chore: upgrade version 2023-09-23 20:41:42 +08:00
Steven 89c24415a6 chore: update not found page 2023-09-23 20:39:01 +08:00
Steven 0d803bf45f chore: update dark mode styles 2023-09-23 20:30:47 +08:00
Steven d4e54f343d feat: update memo detail page 2023-09-23 20:14:07 +08:00
Steven 08a81e79dd chore: update frontend deps 2023-09-23 17:55:26 +08:00
Steven cad789e948 chore: update frontend deps 2023-09-21 23:41:05 +08:00
Steven 4de18cfab1 chore: remove unused deps 2023-09-20 21:24:46 +08:00
Steven 5cec1a71da chore: update access token generator 2023-09-20 20:48:34 +08:00
Steven ae1e22931f chore: auto remove current access token when sign out 2023-09-20 19:24:26 +08:00
Steven a60d4dee41 chore: remove lazy loading image 2023-09-19 23:06:30 +08:00
Steven 7da10cd367 chore: update telegram integration folder 2023-09-19 22:35:20 +08:00
Steven 6d45616dbe chore: add cors middleware 2023-09-19 20:34:25 +08:00
Fabian Wünderich ad326147f1 chore: fix typo in german localization (#2256)
Fix typo in german localization

Signed-off-by: Fabian Wünderich <fabian@wuenderich.de>
2023-09-19 20:21:32 +08:00
Steven 465b173b36 chore: fix resource int type 2023-09-19 09:05:34 +08:00
Steven 9bf1979fa8 fix: list resources 2023-09-19 08:24:24 +08:00
Steven 0a811e19ba chore: remove arm/v7 form platforms 2023-09-19 00:34:27 +08:00
Steven e119acb0e9 chore: remove unused platform of test image 2023-09-19 00:08:58 +08:00
Steven 0f1e87bd93 chore: update test image platforms 2023-09-18 23:28:28 +08:00
Steven f9f2f549af chore: update dockerfile 2023-09-18 23:23:13 +08:00
Steven d665adf78b chore: remove outdate build artifacts action 2023-09-18 22:56:39 +08:00
Steven 1c27824e58 chore: upgrade version 2023-09-18 22:54:44 +08:00
Steven 14adcb56da chore: update resource description 2023-09-18 22:46:24 +08:00
Steven b452d63fa6 chore: skip compose memo error 2023-09-18 22:41:49 +08:00
Steven e2b82929ab chore: fix daily review params 2023-09-18 22:38:52 +08:00
Steven 8fbd33be09 chore: update username matcher 2023-09-18 22:37:13 +08:00
Steven bff41a8957 fix: invalid username checks 2023-09-18 22:34:31 +08:00
Steven 2375001453 chore: fix acl interceptor 2023-09-18 21:50:59 +08:00
Zeng1998 462f10ab60 feat: optimize the logic of the checkbox button. (#2227) 2023-09-18 20:37:28 +08:00
Vespa314 58026c52ea fix: heatmap show on wrong date (#2243)
fix: heatmap show wrong date
2023-09-18 13:53:16 +08:00
victorsch 97b434722c fix: content sanitization in getimage endpoint (#2241) 2023-09-18 12:45:26 +08:00
Steven b22d236b19 chore: update golangci-lint version 2023-09-17 23:21:03 +08:00
Steven cc809a5c06 chore: update github action trigger 2023-09-17 23:18:18 +08:00
Steven cd0ea6558d chore: update golangci-lint config 2023-09-17 22:55:13 +08:00
Steven 9eb077c4af chore: update service clients 2023-09-17 21:12:23 +08:00
Steven 6eeee6b704 docs: add buf to development guide 2023-09-17 20:56:03 +08:00
boojack b13042d644 chore: move buf generated code to gitignore (#2236) 2023-09-17 20:55:05 +08:00
Steven d09e3c3658 chore: remove buf es generator 2023-09-17 20:14:45 +08:00
Steven 72ca4e74ee refactor: impl part of grpcweb 2023-09-17 19:20:03 +08:00
Steven d5c1706e9c chore: update api middlewares 2023-09-17 18:11:13 +08:00
Steven 3a1f82effa fix: migration script 2023-09-16 14:10:51 +08:00
Steven a3d7cc9392 fix: migration script 2023-09-16 14:01:05 +08:00
Steven 178a5c0130 chore: upgrade version to 0.15.0 2023-09-16 12:46:26 +08:00
Steven b233eaea97 chore: update docs link 2023-09-16 12:25:57 +08:00
Steven 51137e01ef chore: update resource description 2023-09-16 11:53:16 +08:00
Steven fb1490c183 feat: impl resources list page 2023-09-16 11:48:53 +08:00
Steven 4424c8a231 chore: add resource service definition 2023-09-16 00:11:07 +08:00
Steven 723e6bcdae refactor: update resources page 2023-09-15 22:25:07 +08:00
Steven d1156aa755 chore: update account setting styles 2023-09-15 22:09:51 +08:00
Steven 4e49d3cb22 chore: update frontend deps 2023-09-15 21:50:50 +08:00
Athurg Gooth 13c7871d20 chore: update vite dev server proxy setting (#2222)
fix vite proxy setting to keep the request headers
2023-09-15 21:49:34 +08:00
Athurg Gooth 137c8f8a07 chore: better date picker (#2220)
* Add buttons to increase year in DatePicker

* Show month with padding 0 to keep DatePicker size
2023-09-15 21:48:52 +08:00
Athurg Gooth 0c0c72c3ca chore: optimize layout of image resources (#2221)
Optimize layout of image resource
2023-09-15 17:58:17 +08:00
steven e6a90a8be8 chore: register reflection grpc server 2023-09-15 17:57:45 +08:00
Steven e65282dcc5 chore: fix user state loader 2023-09-15 09:10:16 +08:00
Steven 28a1888163 chore: fix user seed data 2023-09-15 08:55:18 +08:00
Steven 8824ee9b9d chore: fix user state loader 2023-09-15 08:43:52 +08:00
Steven 936fe5ac9d chore: update state initial loader 2023-09-15 08:31:19 +08:00
Steven f5802a7d82 chore: update access token ui 2023-09-15 08:18:30 +08:00
Steven 33d9c13b7e chore: remove openid field from user 2023-09-14 22:57:27 +08:00
Steven 42bd9b194b feat: impl user access token api 2023-09-14 20:16:17 +08:00
Athurg Gooth 41e26f56e9 chore: persist selected date of DailyReview page (#2219)
* Persist selected date of DailyReview page

* Use hook useLocalStorage instead of useState

* Update web/src/pages/DailyReview.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>
Signed-off-by: Athurg Gooth <athurg@gooth.org>

---------

Signed-off-by: Athurg Gooth <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-09-14 19:57:44 +08:00
Steven 14aa3224ce chore: add readme about protobuf 2023-09-14 19:21:21 +08:00
Steven 8a796d12b4 chore: add user access token setting definition 2023-09-14 19:18:54 +08:00
Athurg Gooth c87df8791b chore: optimize performance of /memo/stats (#2218)
Optimize performance of /memo/stats
2023-09-14 14:18:29 +08:00
Steven f0f42aea9f chore: fix react use imports 2023-09-13 22:56:02 +08:00
Athurg Gooth 626ff5e3a7 feat: notify by telegram while new memo create by HTTP (#2215)
* Inject telegram bot into API service

* Add support for send telegram message

* Send notification by telegram while new memo post
2023-09-13 21:36:43 +08:00
Steven 36209eaef1 feat: add content cache for memo editor 2023-09-13 21:32:21 +08:00
Steven d63715d4d9 feat: implement list memos filter 2023-09-13 20:42:44 +08:00
Kada Liao 9600fbb609 fix: multiple inline latex parsing (#2214) 2023-09-13 17:58:52 +08:00
Steven 04595a5fb1 chore: update resource icons 2023-09-13 09:12:51 +08:00
Kada Liao 9a0ada6756 feat: support LaTeX with react-katex (#2209)
feat: support latex

Co-authored-by: liaoxingyi <liaoxingyi@douban.com>
2023-09-12 23:53:46 +08:00
Steven 416e07cb1f fix: inject additional style and scripts 2023-09-12 23:43:32 +08:00
Steven 58429f88a0 fix: memo filter in daily review 2023-09-12 23:38:13 +08:00
Steven 439d88f06b chore: fix user avatar style 2023-09-12 23:35:10 +08:00
Steven d165ad187c chore: pnpm update 2023-09-12 08:25:57 +08:00
Steven 319f679e30 chore: fix timestamp type 2023-09-10 23:52:35 +08:00
Steven b6d1ded668 chore: adjust initial states 2023-09-10 23:44:06 +08:00
Steven 3ad0832516 chore: use user v2 api in frontend 2023-09-10 22:03:12 +08:00
Steven 93f062d0b9 chore: update user v2 api 2023-09-10 18:56:24 +08:00
Steven 866937787c chore: clean duplicated requests 2023-09-10 11:43:38 +08:00
Steven ca336af4fa chore: update locale checks 2023-09-10 10:53:37 +08:00
Steven 7ec5d07cb8 chore: remove fullscreen button 2023-09-10 10:48:08 +08:00
Steven 2e79fe12e2 chore: remove helm folder 2023-09-10 10:39:46 +08:00
Steven 3df550927d chore: update user profile page 2023-09-10 10:33:22 +08:00
Willian Ricardo Da Silva 44be7201c0 chore: update pt-BR.json (#2196)
* chore: update pt-BR.json

* update import order
2023-09-07 09:23:12 +08:00
boojack 0d50f5bd08 chore: update comments (#2195) 2023-09-06 21:59:20 +08:00
boojack 8b1f7c52aa choer: add system setting api (#2194) 2023-09-06 21:54:12 +08:00
Athurg Gooth 9987337eca fix: all ID from int to int64 to avoid 32bits machine break (#2191)
Fix all ID from int to int64 to avoid 32bits machine break
2023-09-06 21:14:07 +08:00
Takuro Onoue 87a1d4633e chore: update ja.json (#2192)
* Update ja.json

I added the missing lines and translated.

* Update ja.json

I forgot to remove the comma at the end of the column.
I translated the untranslated portions.
2023-09-06 21:10:42 +08:00
boojack c2aeec20b7 chore: upgrade deps version (#2181) 2023-08-27 16:08:39 +08:00
boojack a5b3fb2a6a chore: move cron package to internal (#2180) 2023-08-26 23:13:03 +08:00
boojack c67a69629e chore: update user menu items (#2179) 2023-08-26 23:11:45 +08:00
boojack 18fb02a1ec chore: update swag docs (#2178)
* chore: update swag docs

* chore: update
2023-08-26 08:07:43 +08:00
boojack ad1822d308 chore: update db utils (#2177) 2023-08-26 07:33:45 +08:00
boojack 4af0d03e93 chore: add user profile page (#2175)
chore: some enhancements
2023-08-25 23:10:51 +08:00
boojack 8c312e647d chore: remove auto collapse setting (#2169) 2023-08-24 22:00:48 +08:00
boojack d3bd3ddab0 chore: update some detail styles (#2168)
* chore: update some detail styls

* chore: update
2023-08-24 21:52:16 +08:00
Sandu Liviu Catalin 6c01e84099 feat: add configuration option to bind server to specific address (#2165) 2023-08-24 09:59:23 +08:00
boojack b9b795bf0e chore: add react use (#2157)
* chore: add react use

* chore: update
2023-08-21 02:35:53 +08:00
boojack 19e7731abb chore: generate ts definition (#2156)
* chore: generate ts definition

* chore: update
2023-08-21 02:09:41 +08:00
ti777777 609b24f2ba chore: update zh-Hant.json (#2155)
Update zh-Hant.json

* removed unused entries
* updated the Traditional Chinese translation
2023-08-20 09:18:38 +08:00
Maciej Kasprzyk 735cfda768 fix: tag suggestions positioning (#2151) 2023-08-18 08:41:24 +08:00
Lincoln Nogueira 3f82729e9f chore: update build scripts (#2150)
update developer build scripts, bringing
feature parity between platforms.
2023-08-17 05:40:40 +08:00
Maciej Kasprzyk 077cfeb831 feat: improve tag suggestions (#2126)
* feat: make filtering case insensitive

* fix: wrong letter case when accepting suggestion

* refactor: wrap textarea in TagSuggestions

* fix: less styles not matching common-editor-inputer

* refactor: use explanatory const names for tested value in conditional checks

* feat: style highlighted option

* feat: handle down/up arrow keys

* feat: handle enter or tab to trigger autocomplete

* fix: wrong import

* fix: tab key adding whitespace after auto-completion

* fix: starting a note with a tag

* fix: close on escape

* refactor: early version of removed wrapping and children prop

* refactor: remove unnecessary return false

* refactor: finished rewriting to not wrap editor
2023-08-16 08:54:30 +08:00
boojack 95588542f9 chore: upgrade version to 0.14.4 (#2132) 2023-08-13 23:34:17 +08:00
boojack dd529f845a fix: fetch tags in memo editor (#2131)
fix: fetch tag
2023-08-13 23:27:01 +08:00
boojack 9f8a0a8dd3 fix: lazy rendering checks (#2130) 2023-08-13 23:19:29 +08:00
boojack e266d88edd chore: add acl config (#2128) 2023-08-13 00:06:03 +08:00
YuzeTT 0bb5f7f972 chore: update zh-Hans.json (#2127) 2023-08-12 21:34:01 +08:00
OKIAAAAA 012a5f4907 feat: add helm chart (#2095)
* add helm chart

* fix: remove unnecessary documents
2023-08-12 21:33:13 +08:00
YuNing Chen 409d686f7d chore: minor cleanup (#2124) 2023-08-11 22:34:08 +08:00
Jianwei Zhang c835231d32 feat: add header into resource response (#2120)
Update - add header for get resource
2023-08-10 23:45:30 +08:00
boojack 723c444910 chore: update server tests (#2118) 2023-08-10 09:01:38 +08:00
boojack 35f2d399e2 chore: update api v1 docs (#2117)
* chore: update apiv1 docs

* chore: update
2023-08-09 22:30:27 +08:00
Lincoln Nogueira 4491c75135 feat: add SwaggerUI and v1 API docs (#2115)
* - Refactor several API routes from anonymous functions to regular definitions. Required to add parseable documentation comments.

- Add API documentation comments using Swag Declarative Comments Format

- Add echo-swagger to serve Swagger-UI at /api/index.html

- Fix error response from extraneous parameter resourceId to relatedMemoId in DELETE("/memo/:memoId/relation/:relatedMemoId/type/:relationType")

- Add an auto-generated ./docs/api/v1.md for quick reference on repo (generated by swagger-markdown)

- Add auxiliary scripts to generate docs.go and swagger.yaml

* fix: golangci-lint errors

* fix: go fmt flag in swag scripts
2023-08-09 21:53:06 +08:00
Chris Akring 513002ff60 chore: update zh-Hans translations for "Tag suggestions" (#2110) 2023-08-08 19:12:04 +08:00
boojack 9693940010 chore: update en locale (#2109) 2023-08-08 07:29:29 +08:00
Moris 8747c58c7d feat: fixed heat map colors, updated it.json (#2106)
* Update it.json

* Add files via upload

* Add files via upload
2023-08-08 07:13:35 +08:00
nulta 0fd791c02d feat: update Korean localization (#2105)
Update korean localization
2023-08-08 07:12:57 +08:00
Jasper Platenburg 3a804ce012 feat: update Dutch translation (#2107) 2023-08-08 07:12:43 +08:00
Ghost108 f864ec3730 chore: update de.json (#2101)
* Update de.json

I used the en.json as a template and translated it (german language)

* Update de.json

* Update de.json

* Update de.json

* Update de.json

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-08-07 20:09:48 +08:00
Chris Akring 9503f73115 feat: use user avatar in ShareMemoDialog (#2102)
fix: ShareMemoDialog use user avata
2023-08-07 19:40:43 +08:00
Derek Reiff f9d1080a7d fix: minor spelling and wording changes for en and de (#2096)
Minor spelling and wording changes

I went through some of english and german localizations to correct or add minor things.

Added `invalid-tag-name` to json. Which also means it should be translated elsewhere.
2023-08-07 11:26:57 +08:00
boojack 4d3e4358e8 chore: update docs (#2094) 2023-08-06 11:25:35 +08:00
boojack 843850675f chore: update image displays (#2093) 2023-08-06 10:42:30 +08:00
boojack 726300394b chore: update image checks (#2092) 2023-08-06 10:38:39 +08:00
boojack 5d5d8de9fe fix: get all memo api (#2091) 2023-08-06 10:14:30 +08:00
boojack e097e8331e chore: upgrade version 0.14.3 (#2086) 2023-08-05 22:47:29 +08:00
boojack 7189ba40d3 feat: add lazy rendering in home page (#2085) 2023-08-05 22:14:17 +08:00
boojack 218159bf83 chore: remove openai setting section (#2084) 2023-08-05 21:39:12 +08:00
boojack 238f896907 feat: add system service (#2083)
* feat: add system service

* chore: update
2023-08-05 21:30:23 +08:00
boojack 270a529948 chore: update resource type checks (#2081) 2023-08-05 20:17:33 +08:00
boojack cc400da44e fix: remove translate hook in code block (#2080) 2023-08-05 20:01:32 +08:00
boojack 3df9da91b4 chore: update get memo api (#2079) 2023-08-05 19:51:32 +08:00
boojack 57dd1fc49f chore: initial memo service definition (#2077)
* chore: initial memo service definition

* chore: update

* chore: update

* chore: update
2023-08-05 09:32:52 +08:00
boojack 7c5296cf35 chore: update id type to int32 (#2076) 2023-08-04 21:55:07 +08:00
boojack cbe27923b3 chore: update commands (#2074) 2023-08-03 23:48:21 +08:00
boojack aa26cc30d7 chore: remove memo chat components (#2073) 2023-08-03 23:37:46 +08:00
boojack 1ce82ba0d6 chore: remove shortcut related api (#2072) 2023-08-03 23:33:45 +08:00
boojack d1b0b0da10 chore: remove shortcuts in frontend (#2071) 2023-08-03 23:28:38 +08:00
Athurg Gooth 11abc45440 feat: add command to move blob from local to db (#2026)
* Add `mvrss` command to move blob from local to db

* Add comment for mvrss command
2023-08-03 19:08:39 +08:00
boojack b5a6f1f997 chore: regenerate pnpm lock file (#2056)
* chore: regenerate pnpm lock file

* chore: update

* chore: update
2023-08-02 20:20:34 +08:00
boojack d114b630d2 feat: add prettier sort import plugin (#2058) 2023-07-31 22:26:45 +08:00
boojack 5f819fc86f chore: update auth middleware (#2057)
* chore: update auth middleware

* chore: update

* chore: update
2023-07-31 20:55:40 +08:00
boojack cc3a47fc65 feat: impl auth interceptor (#2055)
* feat: impl auth interceptor

* chore: update

* chore: update

* chore: update
2023-07-30 23:49:10 +08:00
Maciej Kasprzyk 5d3ea57d82 feat: tag suggestions (#2036)
* feat: figure out how to read caret position

* feat: figure out how to read caret position

* feat: create and style Editor/TagSuggestions.txs

* feat: progress on detect when to show and hide

* feat: progress on when to show and hide and setting position

* feat: toggling and exact placement done

* fix: pnpm lock problems

* feat: filter suggestions by partially typed tag name

* style: prettier

* chore: add types package for textarea-caret

* feat: handle option click

* style: prettier

* style: reorder imports

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-30 22:55:45 +08:00
Lilith c1cbfd5766 feat: add system setting to disable password-based login (#2039)
* system setting to disable password login

* fix linter warning

* fix indentation warning

* Prohibit disable-password-login if no identity providers are configured

* Warnings and explicit confirmation when en-/disabling password-login

- Disabling password login now gives a warning and requires a second
  confirmation which needs to be explicitly typed.
- (Re)Enabling password login now also gives a simple warning.
- Removing an identity provider while password-login is disabled now
  also warns about possible problems.

* Fix formatting

* Fix code-style

---------

Co-authored-by: traumweh <5042134-traumweh@users.noreply.gitlab.com>
2023-07-30 21:22:02 +08:00
boojack 9ef0f8a901 feat: add user setting field (#2054) 2023-07-30 09:53:24 +08:00
boojack 470fe1df49 feat: implement part of user service (#2053)
* feat: implement part of user service

* chore: update

* chore: update
2023-07-30 01:35:00 +08:00
boojack 2107ac08d7 chore: add docs generator (#2052) 2023-07-30 00:12:16 +08:00
boojack 89ba2a6540 feat: implement part of tag service (#2051)
* feat: add grpc gateway tempalte

* chore: update

* chore: move directory

* chore: update
2023-07-30 00:00:49 +08:00
boojack 9cedb3cc6c chore: update github actions (#2050) 2023-07-29 20:59:22 +08:00
boojack d0cfb62f35 chore: add tag service proto definition (#2049)
* chore: add tag proto definition

* chore: rename
2023-07-29 20:52:45 +08:00
boojack 9abf0eca1b feat: add buf configuration files and example proto (#2048)
* feat: add proto and buf configuration files

* chore: buf generate

* chore: update comments

* chore: go mod tidy
2023-07-29 19:44:09 +08:00
boojack a6a1898c41 refactor: user v1 store (#2047) 2023-07-29 18:57:09 +08:00
boojack f5793c142c revert: chore: update build docker image actions (#2046)
Revert "chore: update build docker image actions (#2045)"

This reverts commit 8f37c77dff.
2023-07-29 16:09:00 +08:00
boojack 8f37c77dff chore: update build docker image actions (#2045) 2023-07-29 15:59:23 +08:00
Gerald 28aecd86d3 fix: avoid content flash on auto collapse (#2042) 2023-07-29 09:04:34 +08:00
Gerald 95675cdf07 fix: show full content in detail page (#2041)
fix #1373 again
2023-07-28 15:52:50 +00:00
boojack 8328b5dd4a chore: upgrade version to 0.14.2 (#2035)
* chore: upgrade version to `0.14.2`

* chore: remove TestConcurrentReadWrite test
2023-07-26 22:42:38 +08:00
boojack d8d6de9fca fix: get user by username api (#2034) 2023-07-26 22:41:21 +08:00
boojack 56c321aeaa revert: fix: exclude all punctuation chars except underscore in tags (#2033)
Revert "fix: exclude all punctuation chars except underscore in tags (#1974)"

This reverts commit 8c61531671.
2023-07-26 21:11:13 +08:00
Takuro Onoue 756e6a150c chore: update ja.json (#2032)
I think free means freedom, not freemiam.

Fixed some strange expressions in the heatmap section.

Added spaces before and after English words that are in Japanese sentences.
2023-07-26 20:53:14 +08:00
Takuro Onoue 828984c8ec chore: update ja.json (#2030)
Update ja.json

translated one part.
2023-07-26 08:57:53 +08:00
Harry Tran 9da0ca5cb3 feat: add search bar in archived and explore pages (#2025)
* feat: add search bar in archived and explore pages

* Update web/src/pages/Archived.tsx

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-24 11:09:30 +00:00
iMaeGoo dc5f82ac9c feat: update chinese translate (#2023) 2023-07-24 19:08:46 +08:00
Ajay Kumbhare d000083b41 fix: hashtag filter for Unicode characters (#2017) 2023-07-23 19:17:18 +08:00
Mason Sun a9eb605b0f fix: auth api json format (#2021)
Update auth.go

api/v1/auth/相关接口未应用convertUserFromStore方法,会导致User对象获得类型存在问题,导致User定义的`json:`相关的字段转化失效。
导致输出json未被正确格式化
2023-07-23 19:11:29 +08:00
Ajay Kumbhare 5604129105 fix: empty state display issue with resourceList style Grid (#2018) 2023-07-23 19:10:33 +08:00
boojack 04b7a26c03 chore: fix request path (#2014) 2023-07-23 10:12:13 +08:00
boojack 28203bbaf9 chore: fix rss route (#2010) 2023-07-22 21:51:05 +08:00
boojack 9138ab8095 fix: rss route (#2008)
* fix: rss route

* chore: update
2023-07-22 12:58:17 +08:00
boojack 4231ec5a1a chore: upgrade version to 0.14.1 (#2004) 2023-07-22 09:58:03 +08:00
Ajay Kumbhare 55975a46d8 feat: add hindi language translation for i18n support (#2001) 2023-07-22 09:38:54 +08:00
Alexandr Tumaykin 1182545448 fix: add resource.clear to translate (#1999)
Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-21 17:07:05 +08:00
Takuro Onoue 9f3c3ae094 chore: update ja.json (#1996)
It is strange to translate "about" as "Notes について". However, if we define "について" as "about", the sentence becomes "について Memos". It is better not to translate here.
2023-07-21 10:38:06 +08:00
boojack 4c33d8d762 chore: remove unused transaction in store (#1995)
* chore: remove unused transaction in store

* chore: update
2023-07-20 23:15:56 +08:00
Lincoln Nogueira c8961ad489 fix: database is locked (#1992)
* fix: database is locked

The option "_journal_mode=WAL" is currently *not* being applied when
provided in the DSN.

This issue affects only new memos installations, not older ones where
the database journal was properly set to WAL mode by the previous sqlite
library go-sqlite3.

modernc.org/sqlite DSN parsing is different from go-sqlite3. It requires
the `_pragma=` prefix and even some options order matter.

https://gitlab.com/cznic/sqlite/-/issues/115

Closes #1985

* chore: upgraded notes on sqlite DSN
2023-07-20 20:51:25 +08:00
Alexandr Tumaykin f91f09adea feat: use username instead of uid (#1977)
* #1916 replace userId to username

* resolve

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-20 19:48:39 +08:00
Athurg Gooth 336b32004d feat: add AutoBackupInterval in SystemSetting (#1989)
Add AutoBackupInterval in SystemSetting page
2023-07-19 21:39:21 +08:00
Jerry Wang 7b5c13b712 fix: delete multiple resources
* fix: delete multiple resources, close #1986

* chore: remove useless comment
2023-07-19 21:36:02 +08:00
Jianwei Zhang 8bcc2bd715 fix: access token will expired after 24h (#1988) 2023-07-19 08:45:30 +08:00
Ajay Kumbhare 83b771d5cd fix: disable selection of future dates in daily review section (#1983)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error

* chore: Disallow destructuring 't' from useTranslation

This commit adds a linting rule to disallow the destructuring of the 't' property from the result of the useTranslation function call. The no-restricted-syntax rule in the ESLint configuration has been updated to enforce this restriction. The intention is to promote alternative approaches like using the useTranslate hook for localization.

* fix: typo fixed for memoChat

* fix: copy code button toast message

Refactored the code for the "Copy Code" button to utilize i18 strings for displaying the success message. Replaced the hard-coded value with the appropriate i18 string "Code copied successfully."

* fix: #1980 disable selection of future dates in daily review section
2023-07-18 22:21:08 +08:00
EINDEX 8dbc63ed56 docs: add rowStatus parameter for memo api document (#1984)
add missing parameters for memo api
2023-07-18 22:20:22 +08:00
Felipe Martínez 8c61531671 fix: exclude all punctuation chars except underscore in tags (#1974)
* Change tag regex

* Update tests

* Add more tag tests
2023-07-18 01:53:07 +08:00
Ajay Kumbhare b5d4b8eae8 fix: copy code button toast message (#1979)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error

* chore: Disallow destructuring 't' from useTranslation

This commit adds a linting rule to disallow the destructuring of the 't' property from the result of the useTranslation function call. The no-restricted-syntax rule in the ESLint configuration has been updated to enforce this restriction. The intention is to promote alternative approaches like using the useTranslate hook for localization.

* fix: typo fixed for memoChat

* fix: copy code button toast message

Refactored the code for the "Copy Code" button to utilize i18 strings for displaying the success message. Replaced the hard-coded value with the appropriate i18 string "Code copied successfully."
2023-07-18 00:16:55 +08:00
Alexandr Tumaykin e36e5823cd feat(security): disable access for anonymous users, when disablePublicMemos is true (#1966) 2023-07-17 09:12:53 +08:00
Ajay Kumbhare 4ac63ba1f0 chore: disallow destructuring 't' from useTranslation (#1973) 2023-07-16 21:26:26 +08:00
boojack 589b104671 chore: upgrade version to v0.14.0 (#1970)
* chore: upgrade version

* chore: update

* chore: update
2023-07-16 13:48:10 +08:00
boojack 220cba84ae chore: add dev guard for memo chat (#1968) 2023-07-16 13:02:52 +08:00
CorrectRoadH 032509ddba feat: save message to memo (#1940)
* feat: implment backend function

* feat: implment frontend component

* stash

* eslint

* eslint

* eslint

* delete node

* stash

* refactor the style

* eslint

* eslint

* eslint

* fix build error

* stash

* add dep

* feat: save message as memos

* eslint

* eslint

* Update web/src/components/MemosChat/MemosChatMessage.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* stash

* eslint

* eslint

* chore: change translate

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-16 11:51:30 +08:00
5idereal 054ef3dc8d chore: update Traditional Chinese translation (#1967) 2023-07-16 10:19:08 +08:00
boojack 2effacd0a6 chore: add api docs (#1965) 2023-07-15 23:30:20 +08:00
boojack 01f4780655 chore: update detail styles (#1964) 2023-07-15 22:57:57 +08:00
Alexandr Tumaykin 49dd90578b fix: add resource.clear to en.json (#1963) 2023-07-15 20:03:49 +08:00
Ajay Kumbhare 1780225da5 feat: add typeScript support to enforce valid translation keys (#1954)
* #1952 Fix incorrect localization key for sign-up failure message

* feat: add typeScript support to enforce valid translation keys

* feat: add typeScript support to enforce valid translation keys

* fix lint errors

* fix lint error
2023-07-15 10:27:37 +08:00
boojack 5e20094386 chore: add indexes (#1959) 2023-07-15 10:26:31 +08:00
boojack 40a30d46af chore: update db connection params (#1960) 2023-07-15 10:26:19 +08:00
Alexandr Tumaykin 6b17a27a13 feat: update russian translate and new translate message (#1958)
* feat: add russian translate and new translate message

* fix

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-15 10:01:40 +08:00
Felipe Martínez 2a7104e564 fix: exclude commas in tags (#1957) 2023-07-15 10:00:35 +08:00
Ajay Kumbhare 8ca2dac184 fix: incorrect localization key for sign-up failure message (#1953) 2023-07-14 21:43:46 +08:00
Athurg Gooth d9b3501fae feat: add support for auto backup db file (#1950)
Add support for auto backup db file
2023-07-14 20:05:07 +08:00
CorrectRoadH 39351970d0 feat: implement memo chat frontend (#1938)
* feat: implment backend function

* feat: implment frontend component

* stash

* eslint

* eslint

* eslint

* delete node

* stash

* refactor the style

* eslint

* eslint

* eslint

* fix build error

* add dep

* Update web/src/components/MemosChat/ConversationTab.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update web/src/components/MemosChat/ConversationTab.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* feat: change the name

* disable for vistor

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-07-14 13:09:21 +08:00
Athurg Gooth 06dbd87311 chore: split save resource asset (#1939)
* Move resource blob save into a independent function

* Support save resouce blob from Telegram like HTTP API

* Support save resouce blob download from URL to LocalStorage or S3

* fix typo
2023-07-14 11:14:10 +08:00
Alexandr Tumaykin c5a1f4c839 feat: format message from telegram and upload attachments (#1924)
* feat: format message from telegram and download documents

* fix: remove bool in expression

* refactor: convert to markdown

* refactor: resolve remarks and add support new message types

* refactor: resolve remarks

* feat: add test for mime type

---------

Co-authored-by: Александр Тумайкин <AATumaykin@tsum.ru>
2023-07-14 00:18:44 +08:00
Ikko Eltociear Ashimine f074bb1be2 docs: fix typo in deploy-with-render.md (#1946)
reliablity -> reliability
2023-07-14 00:00:23 +08:00
boojack 90e7d02e35 chore: update readme (#1947) 2023-07-14 00:00:08 +08:00
boojack 437e05bd2f chore: update header style (#1945) 2023-07-13 23:15:11 +08:00
Sergei Vassiljev 934f57c92f chore: update MemoRelationListView.tsx (#1933) 2023-07-13 19:42:50 +08:00
Athurg Gooth 3093f80d68 fix: visibility param override the user auth state (#1942)
fix visibility param override the user auth state
2023-07-13 15:20:15 +08:00
Athurg Gooth 11aa01ee2e fix: visibility param override the user auth state (#1941)
fix visibility param override the user auth state
2023-07-13 14:56:43 +08:00
CorrectRoadH d8b6e92813 feat: implement memos chat backend function (#1934)
* feat: implment backend function

* eslint

* eslint

* eslint
2023-07-13 11:25:59 +08:00
Athurg Gooth 6adbb7419c chore: split Go binary and src for dev (#1932)
Split Go binary and src for dev
2023-07-12 15:39:56 +08:00
boojack d4b88c6c86 chore: remove auto signout in auth page (#1927) 2023-07-12 00:16:32 +08:00
boojack 698380f940 chore: update seed data (#1928) 2023-07-12 00:16:19 +08:00
Cyang39 dcac442ebf chore: change dropdown's background color in dark mode (#1925)
#1919
2023-07-11 22:37:04 +08:00
boojack da70917b08 chore: update auth page (#1920)
* chore: update auth page

* chore: update
2023-07-09 21:13:26 +08:00
boojack 0292f472e0 chore: add data empty placeholder (#1913) 2023-07-08 13:04:12 +08:00
boojack 7e391bd53d chore: remove resource public id (#1912)
* chore: remove resource public id

* chore: update
2023-07-08 11:29:50 +08:00
Peng Ding 2157651d17 update zh-Hans & zh-Hant translations (#1909) 2023-07-07 08:40:35 +08:00
boojack 0e05c62a3b chore: update common utils (#1908) 2023-07-06 22:53:38 +08:00
boojack a7573d5705 refactor: migrate memo to apiv1 (#1907)
* refactor: migrate memo to apiv1

* chore: update

* chore: update

* chore: update

* chore: upate

* chore: update

* chore: update
2023-07-06 21:56:42 +08:00
boojack 1fa9f162a5 refactor: migrate resource to apiv1 (#1901) 2023-07-06 00:01:40 +08:00
Athurg Gooth 5ea561af3d feat: add support for purged resource link (#1897)
Add support for purged resource link
2023-07-05 21:56:13 +08:00
Athurg Gooth 2033b0c8fa fix: skip auth on /api/v1/status to avoid sign up while token invalid (#1895)
Skip auth on /api/v1/status to avoid sign up while token invalid
2023-07-05 13:55:04 +08:00
Athurg Gooth 1c07ae2650 fix: escape on resource filename (#1892)
add escape on resource filename
2023-07-04 10:06:11 +08:00
boojack 5b6c98582e refactor: migrate storage to apiv1 (#1890)
* refactor: migrate storage to apiv1

* chore: update

* chore: update

* chore: update
2023-07-04 10:05:57 +08:00
Athurg Gooth 0af14fc81a fix: invalid orientation of image thumbnail in Apple devices (#1891) 2023-07-04 09:05:56 +08:00
Athurg Gooth 833fd23820 fix: OpenID was disappear sometimes (#1886)
Fix openid was disapear sometimes
2023-07-03 19:10:24 +08:00
Jiraiya8 d46126c5c3 fix: header archived id (#1888)
Co-authored-by: qingbo <qingbo@jingling.group>
2023-07-03 19:09:59 +08:00
Athurg Gooth 811c3e8844 fix: auto expand height of setting page (#1885) 2023-07-03 13:35:55 +08:00
boojack 223404a240 chore: update memo seed data (#1884) 2023-07-02 23:58:02 +08:00
boojack 31373be172 chore: remove unused packages (#1880) 2023-07-02 19:41:56 +08:00
boojack 66e65e4dc1 refactor: migrate definition to api v1 (#1879)
* refactor: user api v1

* refactor: system setting to apiv1

* chore: remove unused definition

* chore: update

* chore: refactor: system setting

* chore: update

* refactor: migrate tag

* feat: migrate activity store

* refactor: migrate shortcut apiv1

* chore: update
2023-07-02 18:56:25 +08:00
Phong H b84ecc4574 chore: update vi.json locale (#1878)
Co-authored-by: phong.bnh <phong.bnh@globalfactories.com>
2023-07-02 16:41:03 +08:00
boojack 9a8d43bf88 chore: update user store names (#1877)
* chore: update user store names

* chore: update
2023-07-02 14:27:23 +08:00
boojack ca770c87d6 chore: upgrade version to v0.13.2 (#1873) 2023-07-01 18:01:51 +08:00
boojack c83fd1de38 chore: update dialog overflow style (#1872) 2023-07-01 17:37:43 +08:00
boojack db8b8f0d58 chore: remove unused kit components (#1871) 2023-07-01 12:34:37 +08:00
CorrectRoadH 30fae208c2 fix: pin memos of other people (#1870) 2023-07-01 12:04:49 +08:00
boojack 5fe644a3b6 chore: add jwt middleware in apiv1 (#1869) 2023-07-01 00:03:28 +08:00
CorrectRoadH a108f5e212 fix: ignore internalpath field when creating resource (#1868)
* fix/to_valid_token

* eslint

* revert

* fix/invalid_internalpath_file_upload
2023-06-30 23:50:55 +08:00
CorrectRoadH c9aa2eeb98 fix: validate access token (#1867)
* fix/to_valid_token

* eslint

* revert

* Update server/jwt.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-30 14:59:52 +00:00
Vespa314 63d6b6f9f9 chore: listMemos sort by id for memos post/update at the same time (#1866) 2023-06-30 22:56:31 +08:00
boojack 847b4605f4 chore: update dark mode style (#1864) 2023-06-30 08:40:13 +08:00
boojack 6b3748e2a3 chore: update setting page styles (#1863)
* chore: update setting page styles

* chore: update
2023-06-29 23:17:01 +08:00
boojack 6a78887f1d chore: update store types name (#1862) 2023-06-29 22:55:03 +08:00
boojack 7226a9ad47 chore: update idp store (#1856) 2023-06-26 23:46:01 +08:00
boojack b44f2b5ffb chore: migrate user setting to api v1 package (#1855)
* chore: migrate to api v1 package

* chore: update
2023-06-26 23:06:53 +08:00
boojack 07e82c3f4a fix: schema migrate (#1846)
* fix: schema migrate

* chore: update
2023-06-20 12:18:04 +08:00
boojack b34aded376 refactor: migration idp api (#1842)
* refactor: migration idp api

* chore: update
2023-06-17 22:35:17 +08:00
boojack 4ed9a3a0ea refactor: migrate auth routes to v1 package (#1841)
* feat: add api v1 packages

* chore: migrate auth to v1

* chore: update test
2023-06-17 21:25:46 +08:00
boojack f1d85eeaec chore: upgrade pnpm version (#1833)
* chore: upgrade pnpm version

* chore: update
2023-06-15 22:35:41 +08:00
SedationH 1b0efc5548 fix: use ?? in className use (#1829) 2023-06-15 20:05:19 +08:00
May Kittens Devour Your Soul 6dca551164 chore: update hr.json (#1832)
Update hr.json

Updated Croatan [some fixes]
2023-06-15 19:27:13 +08:00
Athurg Gooth 7694597728 feat: Add suppport for tap to reload on PWA (#1827)
* Add suppport for tap to reload on PWA

* Clean empty className

* Move click event to site title

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-14 22:33:46 +08:00
Athurg Gooth 4d59689126 feat: set memo visibility in telegram (#1824)
* Add telegram.Bot in MessageHandler

* Change single message handler like group messages

* Move message notify wrapper from plugin to server

* Add keyboard buttons on Telegram reply message

* Add support to telegram CallbackQuery update

* Set visibility in callbackQuery

* Change original reply message after callbackQuery

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-14 22:10:01 +08:00
May Kittens Devour Your Soul 8f7001cd9f feat: add croatian locale (#1822)
* Create hr.json

Croatian Language

* Update user_setting.go

* Update i18n.ts

* Update hr.json

* Update web/src/i18n.ts

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-14 22:09:19 +08:00
David Angel 781b1f7b3a chore: add classnames for easy logo/server name customizations via CSS. (#1828)
Update MemoDetail.tsx
2023-06-14 21:03:38 +08:00
Athurg Gooth e6c9f2a00e feat: add support for download resource from link (#1800)
* Add support for download resource from link

* Parse external link and add file ext name from mime info

* Add zh-Hans locale for `download-link`

* fix typo on code and comments

* Update server/resource.go

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-06-08 14:35:33 +00:00
Athurg Gooth 5d06c8093c fix: systemSetting in UI changed unexpectedly (#1812)
Fix systemSetting in UI changed unexpectedly

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-08 22:32:57 +08:00
kakik0u c396cc9649 feat: add japanese locale (#1802)
* Add japanese

* Add japanese setting files

---------

Co-authored-by: barappe <121844712+barappe@users.noreply.github.com>
2023-06-08 13:50:48 +08:00
zhangpeng ac5d8b47ca chore: modify the error message when registering a Host user (#1804)
* Modify the error message

* modify the error message
2023-06-07 12:12:23 +08:00
Athurg Gooth 77e8e9ebbd revert: fix: add public base path (#1748) (#1775) (#1806)
This reverts commit d205a7683a.
2023-06-07 10:07:30 +08:00
c14c6b3786 fix: user default 'Basic Setting' should follow server's setting (#1795)
fix: user default 'Basic Setting' should follow system setting
2023-06-07 00:38:50 +08:00
Athurg Gooth c27c6cea13 fix: failed to upload OSS with S3 SDK (#1792)
Fix failed to upload OSS with S3 SDK

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-03 14:38:28 +08:00
boojack 11a385cda6 chore: update upgrade version view (#1791) 2023-06-03 14:32:04 +08:00
boojack 32e2f1d339 chore: update page routes (#1790)
chore: update routers
2023-06-03 13:03:22 +08:00
Athurg Gooth 69225b507b chore: clean Dockerfile to exclude musl-dev (#1787)
Clean Dockerfile to exclude musl-dev install

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-01 20:16:13 +08:00
-Shiken- 2f905eed0d chore: update zh-Hant.json (#1781)
* Update zh-Hant.json

follow these commits to complete zhTW translation:
96021e518a
8628d1e4b2
93d608f050
ce64894abe
845297ec03

* Update web/src/locales/zh-Hant.json

Co-authored-by: Zeng1998 <acan.coder@gmail.com>

* Fix json format error

---------

Co-authored-by: Zeng1998 <acan.coder@gmail.com>
Co-authored-by: Athurg Gooth <github@gooth.org>
2023-06-01 09:03:44 +08:00
Athurg Gooth 55cf19aa2e fix: copy-to-clipboard not works well in Safari (#1779)
* Fix copy-to-clipboard not works well in Safari

* Fix typescript type check failure

* Remove global copy inject in home page

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-06-01 08:53:40 +08:00
boojack dd8c10743d feat: memo editor dialog (#1772)
* feat: memo editor dialog

* chore: update mark

* chore: update
2023-05-30 20:23:26 +08:00
Athurg Gooth 25ce36e495 feat: resource visibility (#1777)
* Add method to query visibility list by memoIDs

* Add function to get visibility by resourceID

* Check resource visibility in /r/:resourceId/:publicId/:filename

* Check resource visibility in /r/:resourceId/:publicId

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-30 19:00:54 +08:00
Gener d205a7683a fix: add public base path (#1748) (#1775) 2023-05-30 18:55:23 +08:00
Athurg Gooth 7e4d71cf58 fix: infinite loop in home page (#1773)
Fix infinite loop in home page

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-30 18:54:58 +08:00
Athurg Gooth 97df1a82c7 feat: add docker compose file for development (#1769)
* Add support to fetch devProxyServer from environment

* Add docker compose file for developer

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 19:49:47 +08:00
Athurg Gooth 845297ec03 refactor: change all Robot to Bot (#1767)
* Change all `Robot` to `Bot`

* Change all `r` of `Bot` to `b`

* Change `Robot` to `bot` in comments

* Fix typo

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 19:49:05 +08:00
Athurg Gooth ddf4cae537 feat: disable CGO_ENABLED (#1766)
* Replace mattn/go-sqlite3 with modernc.org/sqlite

* Disable CGO to make binary work without special c lib

* Replace mattn/go-sqlite3 with modernc.org/sqlite in testing code

* Tidy go module

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 13:29:42 +08:00
Athurg Gooth ce64894abe feat: add telegram proxy support (#1764)
* Add support for reverse proxy of telegram API

* Add Telegram API proxy hint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-29 13:29:21 +08:00
boojack beb4d8ccb9 chore: order by updated ts in memo store (#1761) 2023-05-28 02:04:05 +08:00
boojack e0e59c5831 feat: display memo with updated ts (#1760) 2023-05-28 01:50:09 +08:00
_Jellen 826541a714 feat: update korean localization (#1758) 2023-05-27 22:03:06 +08:00
boojack c40aeb91e6 fix: patch memo row status (#1755) 2023-05-27 11:14:23 +08:00
boojack 2e34ce90a1 chore: upgrade version 0.13.1 (#1754) 2023-05-27 09:09:41 +08:00
GodMeowIceSun 93d608f050 feat(#1568): add "ask ai" section session splitting function (#1711)
* feat(#1568): Added "ask ai" section session splitting function

Added "ask ai" section session splitting function
Optimize the "ask ai" dialogue style

* fix(#1568): Fix wrong attribute "appearance"

* fix(#1568): Add ts type define

* fix(#1568): Add ts type define

* fix(#1568): Resolve the issue of components not being stretched when only user input is available

* feat(#1568): New session automatic switching function

* refactor(#1729): remove unused code

* feat(#1568): New Remove Session Function

New Remove Session Function
Rename some methods
2023-05-27 02:29:54 +08:00
boojack ec26a9702d fix: sso templates (#1753) 2023-05-26 22:25:30 +08:00
boojack dbe8aa1d3a chore: update telegram bot related section (#1750)
* chore: update telegram bot related section

* chore: update
2023-05-26 21:32:44 +08:00
Athurg Gooth 8628d1e4b2 feat: add Telegram bot config UI (#1747)
* Add retry wait for telegram.GetUpdates

* Add support to set telegram robot token from UI

* Change validator of UserSettingTelegramUserID

* Add support to set telegram user id from UI

* Fix typescript check

* Add validator for SystemSettingTelegramRobotTokenName

* Optimize error notice while config telegram params

* Change for review

* Fix telegram user id could not be empty

* Fix telegram robot could not be empty

* Fix for eslint (again)

* Update web/src/components/Settings/SystemSection.tsx

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-05-26 19:16:51 +08:00
Athurg Gooth 4ea5426e18 feat: add support for content search (#1728)
* Change MemoFind.ContentSearch to slice

* Add support for content search

* Change for go-simple sugguest

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-26 18:51:18 +08:00
Athurg Gooth 1282fe732e feat: implement telegram bot plugin (#1740) 2023-05-26 09:43:51 +08:00
boojack a07d11e820 feat: tag parser (#1745) 2023-05-26 09:05:17 +08:00
boojack dbc85fe7e4 feat: image and link parser (#1744)
* feat: image and link parser

* chore: update
2023-05-26 08:43:37 +08:00
boojack 523ef2bba5 chore: update demo banner style (#1743) 2023-05-26 00:47:53 +08:00
boojack de8014dfe8 feat: resource store cache (#1742) 2023-05-26 00:38:27 +08:00
deeshu b42e5c3213 chore: update vscode setting enforcement for go111module="on" (#1738)
vscode setting enforcement for go111module to set on and availability of schema for go extension
2023-05-25 22:00:32 +08:00
boojack ea728d232d refactor: memo store (#1741) 2023-05-25 21:50:37 +08:00
boojack 43819b021e chore: add demo banner (#1739) 2023-05-25 19:29:30 +08:00
boojack e69f7c735b chore(revert): retire demo site (#1733)
Revert "chore: retire demo site (#1659)"

This reverts commit cd2bdab683.
2023-05-24 20:34:07 +08:00
Athurg Gooth 5e792236af fix: infinite loop while daily memos more than DEFAULT_MEMO_LIMIT (#1730)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-24 20:22:16 +08:00
boojack 45c119627b chore: move flags into env variables (#1732) 2023-05-24 20:08:47 +08:00
boojack 65890bc257 feat: implement code block parser (#1727) 2023-05-24 00:31:37 +08:00
boojack 42c653e1a4 feat: implement paragraph and italic parsers (#1725) 2023-05-23 21:11:01 +08:00
boojack 8c34be92a6 feat(gomark): add bold parser (#1724) 2023-05-23 20:49:32 +08:00
boojack fa53a2550a feat: add heading tokenizer (#1723) 2023-05-23 19:52:31 +08:00
Athurg Gooth 616b8b0ee6 feat: introduce publicid to filename template (#1713)
* Add support for `publicid` in PathTemplate

* Use `publicid` by default instead of `filename` in filesystem

* Fix blank string of `systemSettingLocalStoragePath` affect incorrectly

* Add ext name to compatible with OS's preview

* Optimize code for systemSettingLocalStoragePath empty

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-23 19:15:30 +08:00
Athurg Gooth d24632682f chore: add volume define in Dockerfile to avoid data lose (#1718)
Add volume define in Dockerfile to protect data

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-23 18:50:17 +08:00
Athurg Gooth 3b1bab651a fix: system memo visibility was replace by user's setting (#1707)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-22 12:15:00 +08:00
Athurg Gooth 0cea5ebaeb fix: concurrent counter operates (#1706)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-22 11:08:49 +08:00
Zeng1998 1e4a867a9a fix: add thumbnail param only for internal link (#1701)
* fix: add thumbnail param using `URLSearchParams`

* update: add thumnail param only for internal link
2023-05-21 16:41:04 +08:00
CorrectRoadH 6bb0b4cd47 fix: pop search when touch textarea in Android Chrome (#1700)
* fix: pop search when touch textarea

* eslint
2023-05-21 16:31:50 +08:00
CorrectRoadH 56c6f603aa fix: md without search icon (#1699) 2023-05-21 16:28:30 +08:00
boojack 98b3a371f4 fix: patch memo visibility (#1695) 2023-05-21 11:51:13 +08:00
boojack ba8e1e5dc2 chore: add available generator amount flag (#1696) 2023-05-21 11:50:57 +08:00
boojack 467f9080a1 feat: get or generate thumbnail image (#1691) 2023-05-20 22:08:07 +08:00
Athurg Gooth 0894bf13d2 fix: fail to open file while generate thumbnail (#1687)
* Fix fail to open file while generate thumbnail

* Fix for Uncontrolled data used in path expression check

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-20 14:33:59 +08:00
boojack 1d7627dd72 chore: upgrade version 0.13.0 (#1685)
* chore: upgrade version `0.13.0`

* chore: update
2023-05-20 10:16:19 +08:00
boojack d80aa67c97 feat: parse markdown to html format in rss (#1683) 2023-05-20 10:00:21 +08:00
boojack ae1d9adf65 fix: initial system locale (#1684) 2023-05-20 09:39:20 +08:00
boojack b40571095d feat: update memo detail page (#1682)
* feat: update memo detail page

* chore: update
2023-05-20 08:39:39 +08:00
Athurg Gooth 04124a2ace feat: generate thumbnail while get and improve thumbnail quality (#1680)
* Use disintegration/imaging to optimize thumbnail quality

* Generate thumbnail if not exists while GET it

* Changes for `go mod tidy`

* Changes for golang comments lint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 20:07:39 +08:00
Athurg Gooth 2730b90512 feat: highlight the DatePicker's date (#1669)
Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 08:36:08 +08:00
Athurg Gooth 34913cfc83 feat: show thumbnail in resource dashboard (#1666)
* Add image thumbnail instead of an icon

* Change thumbnail size of dashboard to fixed

* Fix for eslint-checks

* Fix for eslint-checks

* Replace css with tailwind

* Remove the parent div used for style

* Show preview while click on the resource

* Change for review Suggested by @Zeng1998

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-19 08:31:32 +08:00
boojack 88799d469c chore: initial gomark plugin (#1678)
chore: initial gomark folder
2023-05-18 21:33:18 +08:00
boojack a07d5d38d6 feat: memo relation part1 (#1677)
* feat: memo relation part1

* chore: update
2023-05-18 21:29:28 +08:00
Stephen Zhou ca5859296a fix: resource url in rss (#1672) 2023-05-18 06:53:20 +08:00
boojack 1a8310f027 chore: update system setting default value (#1665) 2023-05-15 22:59:26 +08:00
Athurg Gooth 041be46732 Add support for image thumbnail (#1641)
* Add a common function for resize image blob

* Auto generate thumbnail for image resources

* Auto thumbnail support for fetch image resources

* Add support for image thumbnail in view

* Fix missing error check

* Fix es-lint check

* Fix uncontrolled data used in path expression

* Remove thumbnail while origin resource been deleted

* Change the thumbnail's storage path

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-15 22:42:12 +08:00
Zeng1998 9eafb6bfb5 chore: add the default value of MaxUploadSizeMiB (#1663) 2023-05-15 21:54:45 +08:00
Lincoln Nogueira 668a9e88c6 fix: File size exceeds allowed limit of 0 MiB (#1664)
fix: File size exceeds allowed limit of 0 MiB

This could happen in databases without "max-upload-size-mib" setting.

Now, both the front-end and the back-end will start with a default
limit of 32 MiB, even if the key is absent.

It is still possible to disable uploads by setting the value to 0.
2023-05-15 21:54:13 +08:00
boojack cd2bdab683 chore: retire demo site (#1659) 2023-05-14 23:35:31 +08:00
CorrectRoadH d72b4e9a98 feat: filter support plain link (#1657)
* fix: unexpected empty lines when copying-pasting

* add ref

* feat: support to filter plain link

* eslint

* fix the typo

* fix the typo

* unified the import path
2023-05-14 23:17:18 +08:00
boojack 2cc5691efd chore: update memo relation types (#1658) 2023-05-14 23:17:05 +08:00
guanzi008 7726ed4245 feat: add build-artifacts.yml (#1583)
* Create main.yml

构建的单文件运行版本几个平台的Windows amd64 ,Linux amd64,Linux arm64

* Rename main.yml to build-artifacts.yml

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-05-13 14:52:50 +00:00
boojack 921d4b996d chore: update help button style (#1656) 2023-05-13 22:52:06 +08:00
Lincoln Nogueira 96021e518a feat: add max upload size setting to UI & UI improvements (#1646)
* Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)

* feat: improve Windows support

- Fix local file storage path handling on Windows

- Improve Windows dev script

* feat: add max upload size setting to UI & more

- feat: add max upload size setting to UI

- feat: max upload size setting is checked on UI during upload,
but also enforced by the server

- fix: overflowing mobile layout for Create SSO, Create Storage
and other Settings dialogs

- feat: add HelpButton component with some links to docs were appropriate

- remove LearnMore component in favor of HelpButton

- refactor: change some if/else to switch statements

- refactor: inline some err == nil checks

! Existing databases without the new setting 'max-upload-size-mib'
will show an upload error, but this can be user-fixed by simply
setting the value on system settings UI.

* improvements requested by @boojack
2023-05-13 22:27:28 +08:00
boojack 5c5199920e chore: seed data for new user (#1655) 2023-05-13 22:25:15 +08:00
CorrectRoadH e1c809d6f1 fix: unexpected empty lines when copying-pasting (#1654) 2023-05-13 22:08:54 +08:00
Athurg Gooth 218009a5ec fix: wrong position of UsageStatItem's popup (#1647)
* fix: wrong position of UsageStatItem's popup

* Replace TAB into Space for eslint

---------

Co-authored-by: Athurg Feng <athurg@gooth.org>
2023-05-12 22:07:53 +08:00
Lincoln Nogueira 5340008ad7 feat: improve Windows support (#1645)
* Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)

* feat: improve Windows support

- Fix local file storage path handling on Windows

- Improve Windows dev script
2023-05-10 08:03:55 +08:00
CorrectRoadH 700fe6b0e4 fix: return pinned status after edit (#1629)
* stash

* query pinned status after patch

* eslint

* refactor query

* eslint

* process specify case

* add test

* Update memo.go
2023-05-09 09:03:09 +08:00
boojack 9b8d69b2dd chore: add vacuum memo relation to dev guard (#1644)
* chore: add vacuum memo relation to dev guard

* chore: update
2023-05-09 09:02:59 +08:00
Zeng1998 84546ff11c chore: show server name instead of "MEMOS" (#1639) 2023-05-09 08:24:13 +08:00
Zeng1998 885a0ddad0 chore: add size for s3 resource (#1638) 2023-05-09 08:17:26 +08:00
Lincoln Nogueira 3b76c6792c feat: add preliminar Windows support (#1636)
Add preliminar Windows support for both
development and production environments.

Default profile.Data will be set to "C:\ProgramData\memos" on Windows.
Folder will be created if it does not exist, as this behavior is
expected for Windows applications.

System service installation can be achieved with third-party tools,
explained in docs/windows-service.md.

Not sure if it's worth using https://github.com/kardianos/service
to make service support built-in.

This could be a nice addition alongside #1583 (add Windows artifacts)
2023-05-09 08:16:38 +08:00
jonny 4605349bdc chore: update Chinese name translation (#1630) 2023-05-06 07:36:22 +08:00
Stephen Zhou ff447ad22b feat: support file sorting when uploading (#1627) 2023-05-03 19:18:29 +08:00
Stephen Zhou c081030d61 chore: lock pnpm version (#1628) 2023-05-03 19:14:21 +08:00
boojack e3496ac1a2 refactor: memo editor components (#1625) 2023-05-03 19:13:37 +08:00
boojack 8911ea1619 chore: update related time format (#1621)
chore: update related time
2023-05-02 08:54:51 +08:00
boojack 34700a4c52 chore: check allow sign up setting in sso (#1620) 2023-05-02 08:45:03 +08:00
boojack b6564bcd77 feat: implement memo relation server (#1618) 2023-05-01 16:09:41 +08:00
Peng Ding 6e6aae6649 feat: update zh-Hans translations and minor fixes in locale_updater.py (#1615)
* update zh-Hans translations

* minor update

* update instruction part

* print json_value for debugging purpose

* update post requests related

* machine translate with chunks to get around {{field}}
2023-05-01 13:27:08 +08:00
João Nuno Mota b98f85d8a7 feat: add infinite scroll for memos (#1614)
Add infinite scroll for memos on home
2023-05-01 13:26:15 +08:00
João Nuno Mota 3314fe8b0e fix: failed eslint checks (#1616) 2023-05-01 08:38:35 +08:00
powersee f12163bc94 feat: add linux/arm/v7 to docker build action (#1610) 2023-04-29 00:40:15 +08:00
CorrectRoadH f7a1680f72 fix: only delete last file when select multiple files #1576 (#1578)
* fix the bug can't delete multiple files #1576

* using useEvent instead of useRef

* delete unused code

* delete unused code

* change hook file name

* refactor the useEvent

* delete unnecessary export

* fix import

* Apply suggestions from code review

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-04-28 16:17:08 +00:00
boojack 4603f414db chore: add system setting cache (#1609) 2023-04-28 00:02:54 +08:00
deeshu 884dca20b3 fix: reappearing of dialog should add body scrolling class (#1602)
When dialog is reappeared after being in a hidden state. Then reappeaning should block further body scrolling for consistent UX.
2023-04-27 07:16:15 +08:00
Max Malm dbb544dc92 feat: read content from search params (#1607) 2023-04-27 07:15:40 +08:00
deeshu 3fad718807 fix: memo content availability for visitor mode (#1605) 2023-04-26 21:57:01 +08:00
boojack fab8a71fd2 feat: implement memo relation store (#1598)
* feat: implement memo relation store

* chore: update
2023-04-25 23:27:38 +08:00
Barry 7776a6b7c6 docs: update readme with MemosGallery (#1590)
- add: https://github.com/BarryYangi/MemosGallery

A simple gallery static page based on the memos api, I think it might be useful for some people, so I just post it up. Close this if not necessary.
2023-04-25 22:27:02 +08:00
boojack cd6ab61c2d chore: add memo_relation (#1585) 2023-04-25 22:26:45 +08:00
_Jellen 00f69d683a feat: update Korean translation (#1592)
Update Korean translation

- add missing keys
- polish some translations
- remove trailing whitespaces
2023-04-23 20:13:34 +08:00
boojack 0e70de4003 chore: split memo resource api (#1587) 2023-04-22 10:42:24 +08:00
boojack 35efa927b6 chore: update readme with docs (#1586) 2023-04-22 10:25:32 +08:00
Antzed 1ff03e87c2 docs: upgrade on fly.io (#1582) 2023-04-22 09:34:36 +08:00
boojack edf934efbb chore: update memo style (#1581) 2023-04-21 14:46:41 +08:00
-Shiken- d0815f586e feat: update zh-tw translation to latest file format (#1569)
* update zh-tw translation to latest file format

* Update zh-Hant.json

* Update web/src/locales/zh-Hant.json

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-04-19 20:22:23 +08:00
Yang 685a23bce8 feat: add auto collapse feature for all memos issue #1463 (#1550)
* add auto collapse feature

* fix some styles

* pass eslint

---------

Co-authored-by: liyang <liyangg@umich.edu>
2023-04-18 10:05:36 +08:00
boojack 0aa7085303 chore: add enclosure to rss (#1559) 2023-04-17 23:26:56 +08:00
boojack 994d5dd891 feat: server tests (#1556)
* feat: server tests

* chore: update
2023-04-17 21:34:59 +08:00
deeshu e62a94c05a feat: hiding dialog using X button should remove class "overflow-hidden" (#1555)
Hiding dialogs result in the body to stay frozen due to mounting behaviour of the dialog, but using 'X' button hides the dialog and won't let user scroll any further. Removing overflow behaviour during hiding procedure will improve User Experience.
2023-04-17 20:13:33 +08:00
Manu 2b83572641 fix: the broken install docs link (#1554) 2023-04-17 19:00:13 +08:00
boojack 5f8aae69e4 chore: update save button style (#1542) 2023-04-16 15:47:01 +08:00
boojack 73b8d1dd99 fix: revert hide ask ai button (#1539) 2023-04-16 10:55:44 +08:00
boojack 58fa00079b chore: update version to 0.12.2 (#1538) 2023-04-16 10:40:21 +08:00
boojack 3060dafb45 chore: update resource link template (#1537) 2023-04-16 10:31:03 +08:00
boojack 5cb436174d chore: remove search key binding (#1536) 2023-04-16 10:03:33 +08:00
boojack 541fd9c044 chore: update window resize listener (#1535) 2023-04-16 10:00:49 +08:00
boojack 7d6934d00c fix: rss link (#1534) 2023-04-16 09:51:03 +08:00
João Nuno Mota 2c328a4540 feat: hide ask ai button when key is empty (#1515)
* Add option to hide Ask AI and update dev version

* Fix formatting according to eslint

* Replace option to hide Ask AI with auto hiding based on config

* Fix golangci-lint errors

* Remove showAskAI logic from OpenAPI
2023-04-16 00:54:33 +08:00
boojack 648634d376 chore: use pnpm (#1533)
* chore: use pnpm

* chore: update
2023-04-16 00:47:40 +08:00
Fog3211 a654a1cb88 fix: toast overload max size error (#1531)
Co-authored-by: Fog3211 <23151576+Fog3211@users.noreply.github.com>
2023-04-16 00:39:31 +08:00
boojack ef02519e72 chore: regenerate yarn lock file (#1530) 2023-04-15 09:12:45 +08:00
Lincoln Nogueira 557278fac0 feat: improve i18n support as a whole (#1526)
* feat: improve i18n support as a whole

- Remove dayjs in favor of /helpers/datetime.ts, which uses
Intl.DateTimeFormat and Date. Dayjs is not exactly i18n friendly
and has several locale related opened issues.

- Move/refactor date/time code from /helpers/utils.ts to
/helpers/datetime.ts.

- Fix Daily Review weekday not changing according to selected date.

- Localize Daily review weekday and month.

- Load i18n listed strings from /locales/{locale}.json in a dynamic way.
This makes much easier to add new locales, by just adding a properly
named json file and listing it only in /web/src/i18n.ts and
/api/user_setting.go.

- Fallback languages are now set in /web/src/i18n.ts.

- Full language codes are now preffered, but they fallback to 2-letter
codes when not available.

- The locale dropdown is now populated dynamically from the available
locales. Locale names are populated by the browser via
Intl.DisplayNames(locale).

- /web/src/i18n.ts now exports a type TLocale from availableLocales
array. This is used only by findNearestLanguageMatch(). As I was unable
to use this type in ".d.ts" files, I switched the Locale type from
/web/src/types/i18n.d.ts to string.

- Move pretty much all hardcoded text strings to i18n strings.

- Add pt-BR translation.

- Remove site.ts and move its content to a i18n string.

- Rename zh.json to zh-Hans.json to get the correct language name on
selector dropdown.

- Remove pt_BR.json and replace with pt-BR.json.

- Some minor layout spacing fixes to accommodate larger texts.

- Improve some error messages.

* Delete .yarnrc.yml

* Delete package-lock.json

* fix: 158:28  error  Insert `⏎`  prettier/prettier
2023-04-15 08:56:03 +08:00
Zeng1998 5652bb76d4 fix: incorrect date parsing (#1527)
* fix: incorrect date parsing

* fix eslint
2023-04-15 00:54:48 +08:00
Alex Zhao d0c40490a7 feat: add HostnameImmutable to aws endpoint config (#1230)
* add config to support S3-compatible urls like minio

* add comment for HostnameImmutable

* fix linting
2023-04-15 00:17:48 +08:00
CorrectRoadH 630d84348e feat: add resource backend unit test (#1521)
* add resource unit test

* add more resource unit test

* change variable name

* add more test cases

* delete unnecessary line

* eslint

* add more asset
2023-04-13 19:55:18 +08:00
CorrectRoadH 81d4f01b7f feat: add e2e test (#1486)
* add i18n

* add base e2e test

* add multiple test for e2e

* extract the funciton of write memo

* change test sturct

* deteled unused dir

* use fixture

* add fixture

* restruced the project

* feat: add workflow

* feat: change playwright test position

* feat: change playwright test position

* using yarn intead of npm

* change install method

* only enable sign in test

* adjust the order of test

* change report pos

* fix style of e2e workflow

* add review test

* unify locale

* randome write content

* change report pos

* reduce unused wait time

* reduce unused folder

* stash

* merge upstream locale

* change test name

* add test item

* change action name

* add lanuage setting

* add shotscreen

* change name of test

* fix the error of import dep

* fix the error of import dep

* fix the error of filename

* fix the format of workflow

* fix the name error of test case

* feat: change the describe of test case

* feat: remove unused test

* feat: change the fixtures name

* feat: remove unused config

* feat: change docker action

* feat: change the generate method

* feat: extrace screenshot

* feat: change extra path

* feat: change extra path

* feat: screenshot and upload

* feat: change upload filename

* feat: change login method

* feat: change e2e method

* feat: change e2e test

* feat: add wait for login

---------

Co-authored-by: CorrectRoadH <a778917369@gmail.comå>
2023-04-11 22:13:06 +08:00
boojack b5c665cb7e chore: update docker image source (#1511) 2023-04-10 23:39:46 +08:00
Gabe Cook 836387cada fix(ci): fix release builds not having any tags (#1507) 2023-04-10 08:08:38 +08:00
Peng Ding 0020498c10 feat: update Chinese translations in zh.json and zh-Hant.json using locale_updater.py (#1506)
update zh.json and zh-Hant.json using locale_updater.py
2023-04-09 20:57:50 +08:00
_Jellen 66ed43cbcb feat: update and refactor Korean translation data (#1505)
refactor and update ko.json
- added missing translation keys into ko.json
- synced the JSON key order of ko.json with en.json
- removed unused translation data
2023-04-09 20:12:20 +08:00
Gabe Cook c6e1d139f8 feat(ci): Add GHCR mirror and major/minor rolling tags (#1503) 2023-04-09 16:32:27 +08:00
boojack ef7381f032 chore: upgrade version to 0.12.1 (#1499) 2023-04-09 11:51:43 +08:00
boojack df30304d00 chore: update share memo buttons (#1498) 2023-04-09 11:38:30 +08:00
boojack 91a24ef9ce chore: update memo header (#1497)
* chore: update memo header

* chore: update
2023-04-09 11:05:09 +08:00
Luyu Cheng d11083d3b9 fix(css): reorder the font fallback list (#1495) (#1496) 2023-04-09 09:48:42 +08:00
boojack 680b8ede6c chore: adjust header style (#1493) 2023-04-08 21:50:07 +08:00
boojack 4e023e2500 chore: add file type to audio (#1492)
* chore: add file type to audio

* chore: update
2023-04-08 19:16:25 +08:00
boojack 3eac19d258 chore: add ignore version upgrade setting (#1491) 2023-04-08 18:13:51 +08:00
boojack ab867b68d3 chore: add timezone env to dockerfile (#1490) 2023-04-08 17:57:00 +08:00
boojack 8cdc662745 chore: update memo visibility display (#1485) 2023-04-07 08:53:20 +08:00
boojack 204c03e772 chore: update audience name (#1484) 2023-04-07 08:52:13 +08:00
boojack d0ddac296f chore: update store error handler (#1479) 2023-04-06 07:42:39 +08:00
HappyZ 609366da6e chore: add "copy link" for each memo (#1474) 2023-04-06 07:12:12 +08:00
boojack f48d91539e chore: update locale file structure (#1478) 2023-04-06 00:07:10 +08:00
boojack cc23f69f66 chore: update import path (#1477) 2023-04-05 23:31:15 +08:00
Zeng1998 6ceafc1827 fix: unexpected reset of the storage setting (#1475) 2023-04-05 14:37:02 +08:00
Sönke Werner Köster 8c2224ae39 feat: allow instance moderators to post public via the API (#1464) 2023-04-04 22:28:20 +08:00
boojack 6ff7cfddda fix: return external link directly (#1465)
* fix: return external link directly

* chore: update
2023-04-04 08:31:11 +08:00
boojack 5361f76b11 chore: update filename when creating resource (#1460) 2023-04-03 23:16:43 +08:00
boojack bdc00d67b2 chore: add default local storage path (#1457) 2023-04-03 17:13:41 +08:00
boojack 5caa8cdec5 chore: delete resource related file (#1456) 2023-04-03 17:02:47 +08:00
boojack 9ede3da882 chore: update learn more link (#1455) 2023-04-03 15:38:14 +08:00
boojack 836e496ee0 chore: allow remove user avatar (#1454) 2023-04-03 14:52:36 +08:00
boojack 5aa4ba32c9 fix: system setting field name (#1453) 2023-04-03 14:40:29 +08:00
boojack 4419b4d4ae chore: update version and remove isDev flag (#1452)
* chore: update version and remove isDev flag

* chore: update
2023-04-03 14:13:22 +08:00
boojack 1cab30f32f feat: add public id field to resource (#1451)
* feat: add public id field to resource

* feat: support reset resource link
2023-04-03 13:41:27 +08:00
boojack c9a5df81ce chore: update store tests (#1449) 2023-04-03 09:53:36 +08:00
boojack 4f2adfef7b chore: update system setting name convention (#1448) 2023-04-03 09:36:34 +08:00
boojack 8a33290722 chore: update user setting key convention (#1447)
* chore: update user settng key convention

* chore: update
2023-04-03 09:02:02 +08:00
boojack 11cd9b21de chore: update auth form (#1445) 2023-04-02 14:25:38 +08:00
boojack 41c50e758a chore: revert resource visibility changes (#1444) 2023-04-02 14:09:25 +08:00
boojack d71bfce1a0 chore: add usage into heatmap (#1443) 2023-04-02 11:56:09 +08:00
boojack 1ea65c0b60 chore: update logo (#1442)
* chore: update logo

* chore: update
2023-04-02 09:54:52 +08:00
boojack c7a57191bd feat: add jwt auth (#1441)
* feat: add jwt auth

* chore: update
2023-04-02 09:28:02 +08:00
thehijacker e3fc23ccf9 feat: updated Slovenian translation (#1440)
* Fixed some strings and typos

Checked on demo site and saw some string can be improved.

* Update LocaleSelect.tsx

Native name for language
2023-04-02 02:26:33 +08:00
boojack 0baf6b0e19 feat: add test for user store (#1438) 2023-04-01 22:47:19 +08:00
boojack 0cddb358c1 chore: add Slovenian locale (#1437)
chore: add sl locale
2023-04-01 21:34:10 +08:00
thehijacker 741eeb7835 feat: added Slovenian translation. (#1436)
Add files via upload
2023-04-01 13:23:12 +00:00
CorrectRoadH 424f10e180 feat: request pagination for resource(#1425)
* feat: add support for resource page on frontend

* [WIP]feat: add backend support for limit and offset search

* feat: add reducer to add resource

* support fetch all resource when first search

* beautify the fetch ui

* restore file

* feat: add all resource before clear resource

* eslint

* i18n

* chore:change the nane

* chore: change the name of param

* eslint

* feat: setIsComplete to true when first loading resource fully

* fix the bug of fetch

* feat change finally to then

* feat: add await and async to clear and search

* feat: return all resource when fetch

* chore: change variable name

* Update web/src/pages/ResourcesDashboard.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* fix missing const value

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-04-01 16:51:20 +08:00
boojack fab3dac70a chore: remove useListStyle hook (#1434) 2023-04-01 16:38:39 +08:00
boojack 89ab57d738 refactor: update import prefix with alias (#1433) 2023-04-01 16:03:14 +08:00
Dmitry Shemin b03778fa73 feat: update RU i18n locale (#1422)
* feat: Fix i18n and RU locale

* fix: eslint issues

* change the position of deps

---------

Co-authored-by: CorrectRoadH <a778917369@gmail.com>
2023-04-01 15:35:25 +08:00
Xudong Cai d21abfc60c feat: add URLSuffix resource option with S3 (#1428)
* feat: add URLSuffix resource option with S3

* feat: add URLSuffix resource option with S3

* fix: eslint
2023-04-01 15:28:00 +08:00
Xudong Cai 8eed9c267c fix: logo img rounded (#1427)
rounded-full move to img tag
2023-03-30 22:21:29 +08:00
CorrectRoadH 3c2578f666 feat: limit the num of lines for filename (#1424)
* feat: limit the linenum of  filename

* change the implement of line-clamp
2023-03-29 20:27:54 +08:00
CorrectRoadH 526fbbba45 feat: empty selected resource when search resource (#1423)
* feat: empty selected resource when search resource

* eslint
2023-03-29 18:59:51 +08:00
boojack 993ea024fd chore: update demo seed data (#1421) 2023-03-28 22:25:54 +08:00
Dmitry Shemin bc595b40e7 feat: add docs for memos setup after deploying (#1419) 2023-03-27 23:45:02 +08:00
Dmitry Shemin e7ee181a91 feat: add setup cmd (#1418)
This command can be used for automatization of initial application's setup
2023-03-27 21:22:49 +08:00
CorrectRoadH 6b703c4678 feat: add empty placeholder when search result is empty (#1416)
* feat: add empty placeholder when search result is empty

* Update web/src/pages/ResourcesDashboard.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-26 13:07:08 +00:00
boojack dbb095fff4 chore: update list switch style (#1417) 2023-03-26 21:02:40 +08:00
CorrectRoadH adf01ed511 feat: add more resource cover icon (#1413)
* stash: file upload

* feat: add style button

* feat: add style of list

* feat: add checkbox for list

* feat: support file upload by drag

* feat: beautify the ui

* feat: support file upload

* stash

* fix: the resource is incorrectly when upload multiple files

* feat: beautify the ui

* chore: reduce unused line

* stash

* chore: deleted unused line

* chore: deleted unused line

* chore

* chore: change the function declare

* feat: support to prompt file is too large

* feat:drop prompt to cover all element

* fix: eslint

* fix: the name of i18n

* chore: refactor the import deps

* feat: beautify the ui

* feat: support the style of button

* feat: beautify the switch ui

* chore: refactor the component

* chore: refactor the resource item dropdown

* feat: use memo to reduce unused computing in drop

* feat: use memo to reduce the calc of resource list

* chore:change name

* Update web/src/locales/en.json

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chore: the import of  deps

* fix: the window size of fecting data

* feat: support to save the state of style

* remove pnpm-lock

* merge main

* chore: simpify the statement

* fix: delete conflict marker

* feat: add i18n for select

* feat:support dark mode

* eslint

* feat: add more file icon

* feat: delete the storage of resource style

* Update web/src/components/ResourceCover.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-26 20:58:02 +08:00
Stephen Zhou 17ca97ebd1 fix: avatar is not rounded (#1415) 2023-03-26 12:43:15 +00:00
CorrectRoadH 7d89fcc892 feat: add list style for resource dashboard (#1389)
* stash: file upload

* feat: add style button

* feat: add style of list

* feat: add checkbox for list

* feat: support file upload by drag

* feat: beautify the ui

* feat: support file upload

* stash

* fix: the resource is incorrectly when upload multiple files

* feat: beautify the ui

* chore: reduce unused line

* stash

* chore: deleted unused line

* chore: deleted unused line

* chore

* chore: change the function declare

* feat: support to prompt file is too large

* feat:drop prompt to cover all element

* fix: eslint

* fix: the name of i18n

* chore: refactor the import deps

* feat: beautify the ui

* feat: support the style of button

* feat: beautify the switch ui

* chore: refactor the component

* chore: refactor the resource item dropdown

* feat: use memo to reduce unused computing in drop

* feat: use memo to reduce the calc of resource list

* chore:change name

* Update web/src/locales/en.json

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chore: the import of  deps

* fix: the window size of fecting data

* feat: support to save the state of style

* remove pnpm-lock

* merge main

* chore: simpify the statement

* fix: delete conflict marker

* feat: add i18n for select

* feat:support dark mode

* eslint

* feat: delete the storage of resource style

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-26 19:32:53 +08:00
_Jellen e84d562146 feat: update Korean translation (#1414)
add missing translation keys into ko.json
2023-03-26 18:02:36 +08:00
boojack 2e14561bfc chore: update logo assets (#1407) 2023-03-24 08:43:26 +08:00
Stephen Zhou 166e57f1ef fix: image preview dialog overlapping (#1405)
* fix: image preview dialog overlapping

* Update web/src/less/preview-image-dialog.less

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-23 11:57:21 +00:00
boojack eeff159a2d chore: remove weblate badge (#1402) 2023-03-22 22:57:54 +08:00
boojack 547f25178b chore: add rss button in user menu (#1401) 2023-03-22 22:33:59 +08:00
Steven Yan 9c0a3ff83c fix: the expand button's z-index is the same as Header (#1400)
fix: the expand button's z-index is higher than Header
2023-03-22 22:17:01 +08:00
CorrectRoadH 2ba54c9168 feat: upload file by drag and drop (#1388)
* stash: file upload

* feat: support file upload by drag

* feat: beautify the ui

* feat: support file upload

* stash

* fix: the resource is incorrectly when upload multiple files

* feat: beautify the ui

* chore: reduce unused line

* stash

* chore: deleted unused line

* chore: deleted unused line

* chore

* chore: change the function declare

* feat: support to prompt file is too large

* feat:drop prompt to cover all element

* fix: eslint

* fix: the name of i18n

* chore: refactor the import deps

* feat: beautify the ui

* Update web/src/locales/en.json

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chore: the import of  deps

* fix: the window size of fecting data

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-22 22:14:32 +08:00
Zeng1998 026fb3e50e fix: markdown support in blockquote (#1394) 2023-03-21 22:38:38 +08:00
CoffDream af3d3c2c9b fix: daily review page & setting dialog style (#1392) 2023-03-21 09:55:53 +08:00
Shruti Chaturvedi 27a1792e78 chore: update Uffizzi Workflows (#1390)
* Update uffizzi-build.yml

* Update uffizzi-preview.yml
2023-03-21 00:15:43 +08:00
CorrectRoadH 63e0716457 chore: fix typo (#1387) 2023-03-20 13:59:53 +08:00
Zeng1998 f3090b115d feat: support local storage (#1383)
* feat: support local storage

* update

* update

* update

* update
2023-03-19 19:37:57 +08:00
boojack a21ff5c2e3 chore: update project structure (#1382) 2023-03-18 23:07:40 +08:00
boojack ff8851fd9f fix: golangci-lint version (#1381)
* chore: update interface declare

* chore: update args

* chore: update

* chore: update
2023-03-18 22:34:22 +08:00
boojack 573f07ec82 feat: support messages to ask AI (#1380) 2023-03-18 22:07:14 +08:00
Gerald 8b20cb9fd2 fix: make creation time a link to the detail page (#1379) 2023-03-18 22:06:44 +08:00
Zeng1998 7529296dd5 chore: remove {filetype} in path template (#1377)
* chore: remove {filetype} in path template

* fix go-static-check

* update
2023-03-18 22:06:15 +08:00
Zeng1998 7f44a73fd0 fix: show full content in detail page (#1375) 2023-03-18 20:19:32 +08:00
Zeng1998 eb835948b7 chroe: add ids for header elements (#1374)
* chroe: add id for header elements

* fix order of id and class
2023-03-18 20:19:13 +08:00
远浅 70e32637b0 build: update dockerfile for using cache to speed up (#1372) 2023-03-18 10:36:53 +08:00
CorrectRoadH c04a31dcda fix: the dropdown be coverd (#1368) 2023-03-18 10:35:46 +08:00
boojack e526cef754 fix: handle IME mode in editor (#1371)
* fix: handle IME mode in editor

* chore: update
2023-03-17 20:47:55 +08:00
远浅 2ba0dbf50b refactor: use function findMatchingParser to reduce duplicate code (#1367)
* refactor: Use function findMatchingParser to reduce duplicate code

* chore: declare type Parser
2023-03-17 20:46:07 +08:00
CorrectRoadH 4ee8cf08c6 feat: allow resource title mutiple line (#1370) 2023-03-17 20:20:20 +08:00
CorrectRoadH f1f9140afc fix: the incorrectly height of grid row in safari (#1366) 2023-03-17 19:38:59 +08:00
boojack c189654cd9 chore: update resource dashboard style (#1362) 2023-03-15 23:29:43 +08:00
CorrectRoadH 0a66c5c269 feat: new resource dashboard (#1346)
* feat: refator the file dashboard

* feat: support select resouce file

* feat: suppor delete select files

* feat: support share menu, implement rename and delete

* chore: change the color of hover

* chore: refator file dashboard to page

* feat: add i18n for button

* feat: beautify the button

* fix: the error position of button

* feat: only select when click circle instead of whole card

* feat: beautify file dashboard

* chore: factor the filecard code

* feat: using dropdown component intead of component

* feat: add i18n for delete selected resource button

* feat: delete the unused style of title

* chore: refactor file cover

* feat: support more type file cover

* feat: use memo to reduce unused computing in filecover

* feat: when no file be selected, click the delete will error

* feat: store the select resource id instead of source to save memory

* chore: delete unused code

* feat: refactor the file card

* chore: delete unused style file

* chore: change file to resource

* chore: delete unused import

* chore: fix the typo

* fix: the error of handle check click

* fix: the error of handle of uncheck

* chore: change the name of selectList to selectedList

* chore: change the name of selectList to selectedList

* chore: change the name of selectList to selectedList

* chore: delete unused import

* feat: support Responsive Design

* feat: min display two card in a line

* feat: adjust the num of a line in responsive design

* feat: adjust the num of a line to 6 when using md

* feat: add the color of hover source card when dark

* chore: refactor resource cover css to reduce code

* chore: delete unnessnary change

* chore: change the type of callback function

* chore: delete unused css code

* feat: add zh-hant i18n

* feat: change the position of buttons

* feat: add title for the icon button

* feat: add opacity for icon

* feat: refactor searchbar

* feat:move Debounce to search

* feat: new resource search bar

* feat: reduce the size of cover

* support file search

* Update web/src/pages/ResourcesDashboard.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update web/src/components/ResourceCard.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chore: reduce css code

* feat: support lowcase and uppercase search

* chore: reserve the searchbar

* feat: refator resource Search bar

* chore: change the param name

* feat: resource bar support dark mode

* feat: beautify the UI of dashboard

* chore: extract positionClassName from actionsClassName

* feat: reduce the length of search bar

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-15 20:06:30 +08:00
远浅 e129b122a4 refactor: useTranslation in CreateTagDialog (#1356) 2023-03-15 20:05:35 +08:00
远浅 7f30e2e6ff chore: fix typo (#1355) 2023-03-15 07:39:09 +08:00
boojack 29f784cc20 feat: update find resource with linked memo amount (#1354)
* feat: update find resource with linked memo amount

* chore: remove unused test
2023-03-15 00:04:52 +08:00
Wujiao233 28242d3268 fix: expand btn display in front of menu (#1342)
* Docker

* fix:expand btn display issue

* restore Dockerfile

* change Header z-index to 2

* Update web/src/less/memo-content.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-14 08:39:07 +08:00
boojack 8d88477538 chore: rename http getter package (#1349) 2023-03-14 08:38:54 +08:00
boojack 89053e86b3 chore: fix cover bg color (#1337) 2023-03-11 15:23:05 +08:00
boojack 50f36e3ed5 chore: upgrade version to 0.11.2 (#1336) 2023-03-11 13:20:24 +08:00
boojack ca6839f593 chore: remove editor shortcuts (#1334) 2023-03-11 12:31:45 +08:00
boojack e5cbb8cd56 refactor: openAI config system setting (#1333) 2023-03-11 12:26:40 +08:00
boojack 7c92805aac fix: daily review page style (#1332) 2023-03-11 10:08:36 +08:00
boojack a9218ed5f0 refactor: filter store (#1331) 2023-03-11 09:13:54 +08:00
boojack f3f0efba1e feat: update page router (#1330) 2023-03-11 08:43:45 +08:00
boojack ccdcd3d154 feat: fold memo when content overflow (#1327)
* feat: fold memo when content overflow

* chore: update
2023-03-09 23:32:35 +08:00
Cologler 8c774316ae refactor: build storage key (#1326)
* refactor build storage key

* sort imports

* use gofmt to format code
2023-03-09 22:41:48 +08:00
-Shiken- 25da3c073b feat: update zh-tw translation to new file format (#1324) 2023-03-09 12:37:59 +08:00
远浅 6866b6c30d fix: unified tag sorting logic (#1323) 2023-03-09 12:36:11 +08:00
boojack f86816fea2 feat: use react-hot-toast (#1321) 2023-03-09 08:54:14 +08:00
Cologler df6b4b0607 chore: expose port in dockerfile (#1319) 2023-03-09 08:33:33 +08:00
Aswath S 2428e6e190 feat: allow users to customize the refresh time for Daily Reviews (#1313)
* feat: Allow users to customize the refresh time for Daily Reviews

* feat: Allow users to customize the refresh time for Daily Reviews. Lint fix

* feat: Allow users to customize the refresh time for Daily Reviews. change daily review time offset to include only hour

* feat: Allow users to customize the refresh time for Daily Reviews. Retrigger to try CodeQL pass.

---------

Co-authored-by: Aswath S <aswath.s@thoughtworks.com>
2023-03-09 08:26:56 +08:00
Dillon Xu 2ff0e71272 feat: update README.md with memos-desktop (#1317)
Memos client built on electron cross-end framework.
2023-03-09 00:07:56 +08:00
Baptiste Roux 93609ca731 fix: update markdown hyperlink regex (#1315)
* fix: Update markdown hyperlink regex

* chore(lint): Remove unnecessary escape character
2023-03-08 23:22:16 +08:00
boojack 70a187cc18 chore: update ask AI trigger (#1316) 2023-03-08 23:09:15 +08:00
boojack 390e29f850 chore: remove part of less files (#1314) 2023-03-08 22:05:43 +08:00
boojack 3a466ad2a1 chore: update style of home sidebar (#1311) 2023-03-08 21:56:28 +08:00
boojack ccf6af4dc3 fix: request body format in openai api (#1309) 2023-03-08 19:37:50 +08:00
Andrew Pollock ce7564a91b fix: GO-2023-1571 vulnerability (#1308)
* Fix for GO-2023-1571

* Update go.sum to reflect fix for GO-2023-1571
2023-03-08 19:14:09 +08:00
boojack 483c1d5782 feat: update responsible layout (#1306)
* feat: update responsible layout

* chore: update
2023-03-08 09:00:10 +08:00
Jason Chen 65850dfd03 feat: auto focus search bar when sidebar is shown (close #1269) (#1304)
feat: auto focus search bar when sidebar is shown
2023-03-08 08:02:51 +08:00
Zeng1998 d1bafd66c8 feat: allow to filter memos with resources (#1299) 2023-03-07 19:36:36 +08:00
Xiang Jaywhen daa1e9edfb fix: Ask-AI history list reversed when loading answer (#1301) 2023-03-07 19:36:18 +08:00
kimw 008d6a0c81 feat: add GitLab OAuth2 template (#1302) 2023-03-07 19:35:31 +08:00
远浅 7c5fae68fe fix: navigate faild silently (#1300) 2023-03-07 09:24:31 +08:00
Yunwei Xiao c57cea1aaa fix: fix the typo of openai (#1298) 2023-03-07 08:38:41 +08:00
boojack 595dbdb0ec feat: add root layout (#1294) 2023-03-06 21:13:35 +08:00
Wujiao233 003161ea54 feat: support set openai api host (#1292)
* Docker

* feat: support set openai api host

* fix css

* fix eslint

* use API in backend & put host check in plugin/openai

* fix go-static-checks
2023-03-06 20:10:53 +08:00
Zeng1998 fd99c5461c feat(s3): customize filenames via placeholders (#1285)
* feat(s3): customize filenames via placeholders

* fix go-static-checks

* add tips on the frontend

* fix eslint check

* remove yarn.lock

* remove Config.Path

* update tips

* fix

* update
2023-03-06 12:04:19 +00:00
Zeng1998 37366dc2e1 fix: patch user with nil password (#1290) 2023-03-06 19:13:09 +08:00
Zeng1998 c1903df374 fix: correct the storage service state (#1288) 2023-03-06 19:13:00 +08:00
远浅 54374bca05 fix: missing prop key (#1291) 2023-03-06 19:12:50 +08:00
CorrectRoadH ddf1eb0219 feat: automatically change language on first launch (#1278)
* feat: automatically change language to browser language on first launch(#1238)

* Update web/src/store/module/global.ts

* chroe: rename languageCodeCovert to convertLanguageCodeToLocale

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-05 23:45:33 +08:00
Juskinbo 8c5ba63f8c fix: overflow of dialog-content-container (#1277)
* fix: overflow of dialog-content-container

* fix: overflow of dialog-content-container
2023-03-05 23:19:01 +08:00
boojack f7cd039819 chore: rename common to base component (#1279) 2023-03-05 23:08:02 +08:00
boojack 4335897367 chore: remove metrics plugin (#1276)
* chore: remove metrics plugin

* chore: update
2023-03-05 21:42:32 +08:00
boojack 6201dcf1aa chore: simplify readme (#1275) 2023-03-05 21:33:57 +08:00
boojack 5d24fe189d chore: update location store handler (#1273)
* chore: update location store handler

* chore: update search bar
2023-03-05 19:50:50 +08:00
boojack 6d9ead80b2 chore: update demo url (#1256) 2023-03-05 01:18:30 +08:00
boojack bf46a9af68 chore: add heat map to sidebar (#1255) 2023-03-05 01:03:37 +08:00
boojack c6d43581f9 revert: Fix: Markdown hyperlinks with parenthesis take first closing parenthesis as final (#1251)
Revert "fix: Markdown hyperlinks with parenthesis take first closing parenthesis as final (#1213)"

This reverts commit 1b0629bf0f.
2023-03-04 20:54:14 +08:00
boojack 31399fe475 fix: s3 custom path (#1249) 2023-03-04 20:06:32 +08:00
boojack e150599274 chore: upgrade version to v0.11.1 (#1247) 2023-03-04 18:49:50 +08:00
boojack b70117e9f4 chore: update demo screenshot (#1246) 2023-03-04 18:33:17 +08:00
boojack df04e852bf feat: implement openai integration (#1245)
* feat: implement openai integration

* chore: update
2023-03-04 18:22:10 +08:00
boojack dd625d8edc chore: update links reference (#1243) 2023-03-04 15:06:01 +08:00
boojack 6ab58f294e feat: update home layout (#1242) 2023-03-04 13:49:53 +08:00
Alex Zhao 9d4bb5b3af feat: add support for s3 path (#1233)
* add support for path

* fix typo and switch positions with Path and Bucket

* using path method instead of string concatenation
2023-03-04 07:59:44 +08:00
Mehmet Altuğ Akgül e062c9b4a7 feat: add Turkish Translation file (#1202)
* Created tr.json for Turkish Translation

* updated file for trLocale

* Updated for Turkish Locale

* Update i18n.ts

* Update i18n.ts

* Update package.json

* Update package.json

* Update i18n.d.ts

* Update user_setting.go

* Update package.json

* Update web/src/components/LocaleSelect.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update package.json

* Update LocaleSelect.tsx

* Update LocaleSelect.tsx

* Update i18n.ts

* Update i18n.ts

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-02 10:05:15 +08:00
Jason Shawn D' Souza 1b0629bf0f fix: Markdown hyperlinks with parenthesis take first closing parenthesis as final (#1213)
Updating regex to pick up edge case with parentheses
2023-03-01 22:43:13 +08:00
Thareek Anvar M e83ea7fd76 fix: login security issue (#1198)
* fix

* fix bug

* changes

* Revert "changes"

This reverts commit 2b2084c7bd.

* should close the toast if its error also

* no internal errors + sso

* change the text to Incorrect login credentials, please try again
2023-03-01 22:33:43 +08:00
Dan Fiumara 6dab43523d docs: create CustomThemes.md (#1210)
* Create CustomThemes.md

* Update doc/CustomThemes.md

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update doc/CustomThemes.md

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update doc/CustomThemes.md

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update CustomThemes.md

* Update CustomThemes.md

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-03-01 22:32:51 +08:00
Dane Roelofs 4a59965d7a fix: action button container not overflowing memo (#1218) 2023-03-01 22:05:02 +08:00
远浅 71de6613d3 refactor: declare variable for devProxyServer (#1220) 2023-03-01 19:50:43 +08:00
Stephen Zhou e43e04b478 chore: fix unknown at rule @applyless(unknownAtRules) (#1221)
fix: Unknown at rule @applyless(unknownAtRules)
2023-03-01 19:50:09 +08:00
Dan Fiumara 4ab32d4c2c fix: corners not rounded on memos-editor-wrapper (#1209)
* Fixed corners on memos-editor-wrapper

* Remove change in Home.tsx

* Moved change to home.less
2023-03-01 13:38:33 +08:00
Weblate (bot) 1f05b52c4e chore: translations update from Hosted Weblate (#1196)
Translated using Weblate (Turkish)

Currently translated at 19.5% (41 of 210 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 33.3% (70 of 210 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (210 of 210 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (210 of 210 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (210 of 210 strings)

Translated using Weblate (Turkish)

Currently translated at 1.4% (3 of 210 strings)

Translated using Weblate (Turkish)

Currently translated at 0.4% (1 of 210 strings)

Translated using Weblate (Turkish)

Currently translated at 0.0% (0 of 0 strings)

Added translation using Weblate (Turkish)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (210 of 210 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 91.4% (192 of 210 strings)









Translate-URL: https://hosted.weblate.org/projects/memos/web/es/
Translate-URL: https://hosted.weblate.org/projects/memos/web/nl/
Translate-URL: https://hosted.weblate.org/projects/memos/web/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/memos/web/sv/
Translate-URL: https://hosted.weblate.org/projects/memos/web/tr/
Translate-URL: https://hosted.weblate.org/projects/memos/web/zh_Hant/
Translation: memos/web

Co-authored-by: Felipe Nogueira <contato.fnog@gmail.com>
Co-authored-by: Jasper Platenburg <jasperdgp@outlook.com>
Co-authored-by: Luna Jernberg <droidbittin@gmail.com>
Co-authored-by: Onur Ravli <onur@ravli.co>
Co-authored-by: SiriYang <www.yangxinruei@qq.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
2023-02-28 23:53:38 +08:00
Stephen Zhou 3e7fbac926 fix: corner style after scaling (#1199) 2023-02-28 23:52:04 +08:00
CorrectRoadH eda27a60be fix: incorrect sharing image gerneration (#1157) (#1205) 2023-02-28 22:43:42 +08:00
Dan Fiumara 107a2dbe90 feat: update en locale (#1195) 2023-02-28 09:36:07 +08:00
boojack 9577f6dbe8 feat: add resource visibility to user setting (#1190) 2023-02-27 22:16:33 +08:00
boojack ae61ade2b1 chore: add my account entry in user dropdown (#1187) 2023-02-27 21:30:54 +08:00
boojack 977e7f55e5 feat: add visibility field to resource (#1185) 2023-02-27 21:26:50 +08:00
Weblate (bot) c399ff86e0 chore: translations update from Hosted Weblate (#1154)
Translated using Weblate (Portuguese (Brazil))

Currently translated at 25.7% (54 of 210 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 0.0% (0 of 0 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (210 of 210 strings)

Added translation using Weblate (Portuguese (Brazil))





Translate-URL: https://hosted.weblate.org/projects/memos/web/pl/
Translate-URL: https://hosted.weblate.org/projects/memos/web/pt_BR/
Translation: memos/web

Co-authored-by: Felipe Nogueira <contato.fnog@gmail.com>
Co-authored-by: Piotr Wik <p_00@o2.pl>
2023-02-27 20:09:44 +08:00
仝华帅 d43b806c5e fix: model fields are unconsistent with the data queried from the database (#1179)
fix function createActivity typo
2023-02-27 19:50:51 +08:00
Zeng1998 7b7061846c chore: open url in other tabs (#1173)
* chore: open url in other tabs

* update: add `rel="noreferrer"`
2023-02-27 19:50:43 +08:00
Zeng1998 d81cf5cc1b fix: z-index of image preview (#1171) 2023-02-27 19:50:26 +08:00
Zeng1998 4284fd0469 fix: omission of long filename (#1170) 2023-02-27 19:50:09 +08:00
boojack 039b6b247a chore: remove username click event (#1167)
chore: remove user name click event
2023-02-26 23:52:51 +08:00
H3arn a09b2c4eea feat: use accent color when confirming deletion (#1161)
- .final-confirm
2023-02-26 19:37:01 +08:00
Zhizhen He 50a99e9120 fix: correct comments for exported functions and variables (#1158) 2023-02-25 20:48:38 +08:00
Zeng1998 57479b250a chore: remove validators on the frontend (#1156)
* chore: update minlength of username

* remove the validator on frontend

* update
2023-02-25 14:59:29 +08:00
Weblate (bot) e64245099c chore: update translations from Hosted Weblate (#1150)
Translated using Weblate (Polish)

Currently translated at 99.0% (208 of 210 strings)


Translate-URL: https://hosted.weblate.org/projects/memos/web/pl/
Translation: memos/web

Co-authored-by: Piotr Wik <p_00@o2.pl>
2023-02-24 16:14:58 +00:00
boojack d6e4b5e889 chore: fix dispatch memo pinned (#1152) 2023-02-25 00:13:41 +08:00
boojack 6e2e7ac782 fix: remove memo list api (#1151) 2023-02-24 21:11:12 +08:00
boojack 904a6bd97f fix: find memo list order (#1149) 2023-02-24 20:34:54 +08:00
Xiang Jaywhen c24b7097fa fix: function name typo (#1148)
fixed function name typo

“handleAddFilterBenClick” -> "handleAddFilterBtnClick"

[#1147 ](https://github.com/usememos/memos/issues/1147)
2023-02-24 18:09:31 +08:00
boojack cc23d5cafe chore: upgrade version to 0.11.0 (#1143)
* chore: upgrade version to `0.11.0`

* chore: update
2023-02-24 08:31:54 +08:00
boojack 9c5b44d070 feat: update storage schema (#1142) 2023-02-24 00:02:51 +08:00
boojack 84fb8b2288 feat: update storage setting section (#1140) 2023-02-23 23:22:34 +08:00
boojack 6d2d322140 chore: show pinned memos in explore (#1141) 2023-02-23 19:59:18 +08:00
boojack 1517688076 chore: update code structure (#1139)
* chore: update code structure

* chore: update
2023-02-23 00:07:16 +08:00
boojack 29124f56bb chore: update memo service (#1138)
* chore: update memo service

* chore: update
2023-02-22 20:07:55 +08:00
boojack 42d849abfc chore: update explore header style (#1137) 2023-02-22 19:21:08 +08:00
Weblate (bot) d1b307b18f chore: update translations from Hosted Weblate (#1134)
Translated using Weblate (Polish)

Currently translated at 97.1% (204 of 210 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (210 of 210 strings)



Translate-URL: https://hosted.weblate.org/projects/memos/web/pl/
Translate-URL: https://hosted.weblate.org/projects/memos/web/zh_Hant/
Translation: memos/web

Co-authored-by: Piotr Wik <p_00@o2.pl>
Co-authored-by: SiriYang <www.yangxinruei@qq.com>
2023-02-22 00:58:49 +00:00
Weblate (bot) f6d347c5e4 chore: update translations from Hosted Weblate (#1132)
Translated using Weblate (Chinese (Traditional))

Currently translated at 94.2% (198 of 210 strings)


Translate-URL: https://hosted.weblate.org/projects/memos/web/zh_Hant/
Translation: memos/web

Co-authored-by: SiriYang <www.yangxinruei@qq.com>
2023-02-21 21:39:57 +08:00
Weblate (bot) 4fe8476169 chore: update translations from Hosted Weblate (#1128)
Translated using Weblate (Polish)

Currently translated at 79.5% (167 of 210 strings)

Translated using Weblate (Polish)

Currently translated at 0.0% (0 of 0 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (210 of 210 strings)

Added translation using Weblate (Polish)

Translated using Weblate (Korean)

Currently translated at 98.5% (210 of 213 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 97.1% (207 of 213 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 92.0% (196 of 213 strings)

Translated using Weblate (Vietnamese)

Currently translated at 89.2% (190 of 213 strings)

Translated using Weblate (Ukrainian)

Currently translated at 91.5% (195 of 213 strings)

Translated using Weblate (Russian)

Currently translated at 91.5% (195 of 213 strings)

Translated using Weblate (Italian)

Currently translated at 91.5% (195 of 213 strings)

Translated using Weblate (French)

Currently translated at 90.1% (192 of 213 strings)

Translated using Weblate (Spanish)

Currently translated at 91.5% (195 of 213 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (210 of 210 strings)

Deleted translation using Weblate (English (United States))

Translated using Weblate (English (United States))

Currently translated at 0.0% (0 of 0 strings)

Added translation using Weblate (English (United States))

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (210 of 210 strings)

Translated using Weblate (Korean)

Currently translated at 98.5% (207 of 210 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 97.6% (205 of 210 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 93.3% (196 of 210 strings)

Translated using Weblate (Vietnamese)

Currently translated at 90.4% (190 of 210 strings)

Translated using Weblate (Ukrainian)

Currently translated at 92.8% (195 of 210 strings)

Translated using Weblate (Swedish)

Currently translated at 92.8% (195 of 210 strings)

Translated using Weblate (Russian)

Currently translated at 92.8% (195 of 210 strings)

Translated using Weblate (Dutch)

Currently translated at 85.7% (180 of 210 strings)

Translated using Weblate (Italian)

Currently translated at 92.8% (195 of 210 strings)

Translated using Weblate (French)

Currently translated at 91.4% (192 of 210 strings)

Translated using Weblate (Spanish)

Currently translated at 92.8% (195 of 210 strings)

Translated using Weblate (German)

Currently translated at 91.4% (192 of 210 strings)








Translate-URL: https://hosted.weblate.org/projects/memos/web/de/
Translate-URL: https://hosted.weblate.org/projects/memos/web/en_US/
Translate-URL: https://hosted.weblate.org/projects/memos/web/es/
Translate-URL: https://hosted.weblate.org/projects/memos/web/fr/
Translate-URL: https://hosted.weblate.org/projects/memos/web/it/
Translate-URL: https://hosted.weblate.org/projects/memos/web/ko/
Translate-URL: https://hosted.weblate.org/projects/memos/web/nl/
Translate-URL: https://hosted.weblate.org/projects/memos/web/pl/
Translate-URL: https://hosted.weblate.org/projects/memos/web/ru/
Translate-URL: https://hosted.weblate.org/projects/memos/web/sv/
Translate-URL: https://hosted.weblate.org/projects/memos/web/uk/
Translate-URL: https://hosted.weblate.org/projects/memos/web/vi/
Translate-URL: https://hosted.weblate.org/projects/memos/web/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/memos/web/zh_Hant/
Translation: memos/web

Co-authored-by: Luna Jernberg <droidbittin@gmail.com>
Co-authored-by: Piotr Wik <p_00@o2.pl>
Co-authored-by: Yoshino-s <cy-cui@outlook.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
2023-02-21 07:59:02 +08:00
Yoshino-s bbc5ac9f0e feat: make file uplaod support drag/drop (#1129) 2023-02-20 22:17:01 +08:00
_Jellen 29b5c393d1 feat: add Korean translation (#1127)
added Korean translation
2023-02-20 00:54:12 +00:00
boojack b8cc0b1270 chore: update readme with weblate badge (#1126) 2023-02-19 21:55:29 +08:00
boojack b145d8b8a2 chore: update setting dialog style (#1125) 2023-02-19 21:12:16 +08:00
boojack ffe1073292 fix: schema path for demo mode (#1124) 2023-02-19 16:34:15 +08:00
Yoshino-s afaaec8492 feat(mode): add demo mode (#1121)
* feat(mode): add demo mode

* chroe: Update store/db/db.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chroe: Update store/db/db.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-02-19 13:36:45 +08:00
boojack d0b8b076cf feat: implement sign in with SSO (#1119)
* feat: implement sign in with SSO

* chore: update

* chore: update

* chore: update
2023-02-19 09:50:30 +08:00
boojack 708049bb89 feat: add SSO related UI (#1118)
* feat: add SSO related UI

* chore: update
2023-02-18 22:57:45 +08:00
Stephen Zhou 65aa51d525 feat: generate RSS item title and limit item count (#1117)
* feat: generate RSS item title and limit item count

* Update server/rss.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update server/rss.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-02-18 22:20:28 +08:00
boojack cbbd284e7a feat: add store cache for idp (#1116)
feat: add cache for idp
2023-02-18 18:41:52 +08:00
boojack 852903bdbd fix: idp config definition (#1115)
fix: idp definition
2023-02-18 18:31:03 +08:00
Zeng1998 19efacef9c chore: add desc for storage form (#1112) 2023-02-18 18:08:35 +08:00
boojack 0f57629d25 feat: implement idp server (#1111)
* feat: implement idp server

* chore: update
2023-02-18 11:29:12 +08:00
boojack 69726c3925 feat: implement oauth2 plugin (#1110) 2023-02-18 10:50:13 +08:00
boojack 37f9c7c8d6 chore: update avatar max size (#1109) 2023-02-18 10:48:31 +08:00
boojack bcee0bbf3a feat: add avatar to user in frontend (#1108) 2023-02-18 10:00:46 +08:00
boojack 096a71c58b feat: add avatar_url field to user table (#1106)
refactor: add `avatar_url` field to user table
2023-02-17 23:55:56 +08:00
boojack a538b9789b feat: introduce idp table (#1105)
* feat: introduce idp table

* chore: update
2023-02-17 13:06:41 +00:00
boojack c6e525b06f chore: remove unused fields of storage table (#1104) 2023-02-17 20:12:08 +08:00
boojack d29c40dc71 chore: update router loader (#1102) 2023-02-17 08:26:40 +08:00
Jake 4f5f541efe docs: add raycast extension (#1100) 2023-02-16 23:38:30 +08:00
boojack caf054bae7 chore: add beta badge to storage (#1099)
* chore: add beta badge to storage

* chore: update
2023-02-16 21:21:39 +08:00
boojack 7e8011ba34 chore: support deleting storage (#1095) 2023-02-15 22:54:46 +08:00
Ruihang Xia e46f77681d chore(build): anchor setup-buildx-action@v2 to version v0.9.1 (#1089)
Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
2023-02-15 22:16:45 +08:00
Ryan McPherson 0de0a5aa87 chore: make README more comprehensive (#1065)
* Update README.md

* fix typos in readme

* Update README.md

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-02-15 20:52:17 +08:00
boojack 3394380ffa chore: update storage components (#1091) 2023-02-14 22:45:22 +08:00
Zeng1998 2493bb0fb7 feat: storage service frontend (#1088) 2023-02-14 09:56:04 +08:00
Christopher 4641e89c17 feat(system): support for disabling public memos (#1003)
* feat(system): support for disabling public memos

* fix(web/editor): set visibility to private on disabled public memos

* feat(server/memo): find/check if public memos are disabled

* fix(server/memo): handle error for finding system error

* fix(server/memo): unmarshal visiblity when getting system settings

* chore(web): move side effect imports to end

* Update memo.go

---------

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-02-13 16:07:31 +00:00
Xi 28405f6d24 feat: not found page (#1081)
* feat: style for not found page (#1078)

* chore: translation for not found page (#1078)

* feat: add not found page (#1078)

* chore: router for not found page (#1078)

* fix: typo
2023-02-13 23:28:46 +08:00
boojack 5455cb3164 chore: simplify editor (#1087) 2023-02-13 23:27:45 +08:00
Zeng1998 1e4a81dea9 feat: storage service backend (#1086)
* feat: storage service backend

* update go.mod

* update the column name (urlPrefix -> url_prefix)

* update

* update
2023-02-13 19:36:48 +08:00
Jake cbc3373e8e docs: add shortcut for ios (#1083) 2023-02-13 12:41:15 +08:00
boojack 870559046f chore: update skipper name (#1080) 2023-02-12 17:29:23 +08:00
boojack a997e1d10d chore: simplify memo editor component (#1079) 2023-02-12 16:34:42 +08:00
Jake c28d35d8f7 docs: memos-import-from-flomo support wechat reading (#1077) 2023-02-12 07:32:03 +08:00
boojack b92da8f123 fix: check localsetting exists (#1076) 2023-02-11 22:54:13 +08:00
boojack bdf0c44246 chore: add CreatedTs field to MemoCreate (#1073) 2023-02-11 21:32:42 +08:00
Jake 799fb058b4 docs: add memos-import-from-flomo (#1072) 2023-02-11 21:31:38 +08:00
Zeng1998 11924ad4c5 feat: add storage service table (#1070)
* feat: add storage service table

* update json field name

* update table name

* add updated_ts
2023-02-11 20:31:39 +08:00
boojack b11d2130a0 chore: validate external link (#1069) 2023-02-11 17:34:29 +08:00
boojack e0f4cb06b3 chore: update tags order (#1068) 2023-02-11 16:05:52 +08:00
boojack aad97c4c54 chore: update signup api (#1067) 2023-02-11 15:15:56 +08:00
boojack 3590d3f8b6 feat: update store cache (#1066)
* feat: update store cache

* chore: update
2023-02-11 14:19:26 +08:00
Shruti Chaturvedi 6e5be6ba75 chore: add text for Uffizzi Previews in README (#1061) 2023-02-11 08:35:53 +08:00
boojack b366ce7594 fix: delete tag (#1062) 2023-02-10 23:57:02 +08:00
Zeng1998 1eacf5367d chore: upgrade version to 0.10.3 (#1060) 2023-02-10 12:03:18 +08:00
boojack f74d1b7bf8 chore: remove resource cache (#1059) 2023-02-10 08:43:39 +08:00
boojack a004dcf320 fix: pass empty condition in rss (#1058)
fix: handle empty condition in rss
2023-02-10 08:28:14 +08:00
boojack 5df59a48b7 chore: update rss icon style (#1056) 2023-02-09 23:45:48 +08:00
boojack 989208eb45 chore: update resource select dialog (#999)
* chore: update resource select dialog

* chore: update
2023-02-09 23:24:51 +08:00
boojack bec1558488 fix: patch resource id (#1055) 2023-02-09 23:20:36 +08:00
Stephen Zhou 6ff79c5d5c fix: can not input chinese (#1053) 2023-02-09 21:50:51 +08:00
Stephen Zhou 168c4f6950 feat: more rss info (#1052)
* feat: more rss info

* fix: ci
2023-02-09 21:17:15 +08:00
boojack 3e40b9df66 chore: update readme with dark mode demo (#1049) 2023-02-08 20:21:33 +08:00
Stephen Zhou 94f97208e3 chore: setup project workspace for better DX (#1048)
* chore: setup project workspace for better DX

* chore: remove prettier ext
2023-02-08 18:43:13 +08:00
boojack bd9003c24b chore: update readme (#1047) 2023-02-08 08:51:36 +08:00
Nitin Khanna 26700a1ff0 fix: DatePicker should say Wed instead of Web (#1046)
DatePicker should say Wed instead of Web
2023-02-08 08:37:02 +08:00
Stephen Zhou 8b92021b1a fix: editor cursor not in view after smart editing (#1043) 2023-02-07 23:31:43 +08:00
Zeng1998 7cd474dbb7 feat: add setting for double-click of memos (#1036)
* feat: add setting for double-click of memos

* update

* update
2023-02-07 20:35:41 +08:00
boojack 9bf869767d chore: update seed data (#1042) 2023-02-07 20:35:32 +08:00
Zeng1998 9e818cddce feat: tag filter in explore (#1032)
* temp

* Revert "temp"

This reverts commit d2d14b4c57.

* Revert "Revert "temp""

This reverts commit c50be22cb4.

* feat: tag filter in explore page

* update
2023-02-07 20:11:22 +08:00
Stephen Zhou d6fe180ca1 fix: parse chrome or edge urls in plain link (#1034)
fix: parse chrome or urls in plain link
2023-02-07 20:10:13 +08:00
Stephen Zhou 99cac7cac0 fix: scroll when clicking expand button (#1035) 2023-02-07 20:09:30 +08:00
boojack 81f2166912 chore: update code owners (#1041) 2023-02-07 20:08:51 +08:00
boojack 4de65ab55d fix: url encode for tag name (#1031) 2023-02-06 20:28:19 +08:00
Zeng1998 771ef44d82 feat: support enter to signin (#1014) 2023-02-06 20:03:33 +08:00
-Shiken- 76c42c6c9f chore: more translation correction to traditional Chinese (#1028)
* more translation correction to traditional Chinese

To be in line with the language habits of traditional Chinese users

* Update zh-Hant.json
2023-02-06 19:59:33 +08:00
Shruti Chaturvedi 003887d4e0 Use official Uffizzi reusable action (#1027)
* Use official Uffizzi reusable action

* Run preview if build passed successfully
2023-02-06 19:59:05 +08:00
-Shiken- 89743bd1e6 chore: update zh-Hant.json (#1023) 2023-02-05 17:45:50 +08:00
boojack 1ace332152 feat: graceful shutdown server (#1016) 2023-02-03 10:30:18 +08:00
Zeng1998 2d14047c73 fix: pdf resource preview (#1008) 2023-02-02 20:34:24 +08:00
Stephen Zhou 42cd93cf33 fix: show copy button on hover (#1002) 2023-01-31 18:38:58 +08:00
boojack 4a7b764ab3 chore: remove unused flags for sqlite (#997) 2023-01-30 00:03:21 +08:00
Shruti Chaturvedi 1bdb0d465c chore: update Uffizzi GHA for better error-handling (#996)
Update Uffizzi GHA for better error-handling
2023-01-29 18:16:44 +08:00
WY-WY-W 930b54fabd feat: update Traditional Chinese translation (#994) 2023-01-29 09:41:56 +08:00
boojack 5b0a54bfb7 chore: clean package.json (#993)
* chore: clean `package.json`

* chore: update
2023-01-26 00:35:50 +08:00
boojack 6c3ff6de63 chore: get resource blob optional (#991) 2023-01-25 16:11:02 +08:00
boojack dd5a23e36e feat: support creating resource with external link (#988) 2023-01-22 21:16:28 +08:00
boojack 848ecd99ee chore: format SQL (#987)
chore: format sql
2023-01-22 21:16:03 +08:00
boojack 82f61f2a0e chore: upgrade version to 0.10.2 (#983) 2023-01-21 08:56:26 +08:00
boojack c5368fe8d3 chore: update resource dialog style (#982) 2023-01-21 08:46:49 +08:00
Wujiao233 0aaf153717 fix: video and audio can't play on safari (#980)
* fix: video can't play on safari

* fix: audio can't play on safari
2023-01-20 16:52:38 +08:00
Stephen Zhou 942e1f887b feat: scrool to memo after editing (#907) 2023-01-19 20:57:45 +08:00
Wujiao233 b8ab43aa25 feat: support swipe to switch img on touchscreen (#970)
* feat: support swipe to switch img on touchscreen

* fix: fix two or more fingers touch

* fix lint
2023-01-19 20:57:03 +08:00
Wujiao233 a5f3b051f2 fix: round corner issue in resource blocks (#979) 2023-01-19 17:59:37 +08:00
boojack 4ba9767b94 fix: use input instead of textfield (#973) 2023-01-19 09:16:22 +08:00
Zeng1998 12fda38520 feat: add customized logo in share dialog (#969)
* feat: add qrcode in share dialog

* update: change the color

* feat: add customized logo in share dialog

* update: import order

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-01-18 10:52:25 +00:00
Zeng1998 9ed503fd6d feat: add qrcode in share dialog (#964)
* feat: add qrcode in share dialog

* update: change the color

* update: import order
2023-01-18 18:49:48 +08:00
Viet-Anh, Nguyen a8976de634 feat: update Vietnamese translation (#965)
refactor: Update Vietnamese translation
2023-01-18 09:01:53 +08:00
Zeng1998 f8855ddb56 feat: support empty content memo (#963)
feat: support empty-text memo
2023-01-17 20:56:57 +08:00
Jasper Platenburg 288ecc617d feat: issue translator workflow (#956)
Create issue-translator.yml
2023-01-15 21:33:19 +08:00
Ángel Fernández Sánchez 14ec81b65c feat: update Spanish translation (#954) 2023-01-15 08:35:20 +08:00
boojack fae0b64a08 fix: delete tag api (#950)
* fix: delete tag api

* chore: update
2023-01-14 12:08:31 +08:00
boojack 677750ef51 chore: upgrade version to 0.10.1 (#949) 2023-01-14 08:00:07 +08:00
boojack 4cfd000b92 feat: support audio player (#948) 2023-01-14 07:41:17 +08:00
boojack aacaf3f37c chore: remove sponsor with open collective (#947)
chore: update github sponsors
2023-01-14 06:56:17 +08:00
boojack ad4a79a510 chore: update GitHub sponsor (#946)
chore: update github sponsor
2023-01-14 06:51:21 +08:00
boojack 219d2754a0 chore: remove existed tags in suggestion (#944) 2023-01-13 22:37:30 +08:00
boojack 10430a66c3 chore: debounce search text input (#943)
* chore: debounce search text input

* chore: update
2023-01-13 22:33:52 +08:00
Jasper Platenburg c167c21e4e chore: added translation for copy memo link (#942) 2023-01-13 21:22:20 +08:00
boojack 40d25f7dca fix: skip api error for static middleware (#941) 2023-01-13 07:06:15 +08:00
boojack 1441a1df1f chore: update funding with open collective (#940) 2023-01-12 23:48:51 +08:00
boojack b19c3c6db3 feat: update renderer in list (#935) 2023-01-12 08:52:57 +08:00
boojack 8c146aed68 feat: update memo resources style (#933)
* feat: update memo resources style

* chore: update
2023-01-12 00:00:44 +08:00
boojack 805122f45c chore: add User stories section to readme (#932) 2023-01-11 09:21:52 +08:00
sfan5 7d5de1a07e feat: update German translation (#926) 2023-01-08 23:41:48 +08:00
boojack 4b860777cf fix: tag generate in code block (#925) 2023-01-08 13:49:26 +08:00
boojack e29924c8a1 fix: codeblock renderer (#924) 2023-01-08 11:24:28 +08:00
boojack 1847756ade chore: remove escape (#918) 2023-01-07 14:52:47 +08:00
boojack 771c56f485 chore: fix renderer (#917) 2023-01-07 14:07:17 +08:00
boojack 0f057e81e9 fix: version compare (#916)
* fix: version compare

* chore: update
2023-01-07 13:58:42 +08:00
Stephen Zhou 529c9b34a7 fix: missing creator id in shortcut cache (#915)
fix: missing creatot id in shortcut cache
2023-01-07 12:45:55 +08:00
boojack e2e8130f4c fix: sort version (#914) 2023-01-07 11:49:58 +08:00
boojack 46c13a4b7f chore: add skipper for secure (#913) 2023-01-07 10:51:34 +08:00
boojack 96798e10b4 feat: support embed memo with iframe (#912) 2023-01-07 01:56:02 +08:00
boojack 0f8ce3dd16 refactor: return jsx element instead of string in marked (#910)
* refactor: return jsx element instead of string in marked

* chore: update
2023-01-07 00:13:49 +08:00
boojack 491859bbf6 chore: update activity metrics (#908) 2023-01-05 20:56:50 +08:00
boojack f16123a624 chore: update memo create activity (#903) 2023-01-03 23:49:11 +08:00
boojack d50ad9433f feat: persistent session name (#902)
* feat: persistent session name

* chore: update
2023-01-03 23:05:42 +08:00
Zeng1998 92a8a4ac0c feat: support code copy (#901)
* feat: support code copy

* update
2023-01-03 23:05:00 +08:00
helaxious 62f53888ba feat: update docker command description (#893) (#900)
* Add a line on README to help prevent a mistake (#893)

* Update README.md

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2023-01-03 22:40:53 +08:00
boojack 79180928d4 chore: update server activity (#898) 2023-01-03 20:05:37 +08:00
boojack e5550828a0 chore: update activity payload (#891) 2023-01-02 23:18:12 +08:00
Vincenzo Cardone 2e95f6824f feat: add Italian Translation (#890) 2023-01-02 09:41:39 +08:00
boojack 5195012217 feat: add activity table (#888)
feat: introduce activity
2023-01-01 23:55:02 +08:00
boojack a797280e3f chore: update middleware skipper (#887)
* chore: update middleware skipper

* chore: update
2023-01-01 23:26:21 +08:00
boojack 293f88e40c chore: update GitHub action name (#886)
* chore: update github actions name

* chore: update
2023-01-01 22:01:16 +08:00
boojack 861eeb7b0f chore: add skipper in CSRF (#885) 2023-01-01 21:32:17 +08:00
boojack 24b21aa9d7 chore: update version to 0.9.1 (#882) 2022-12-31 15:40:53 +08:00
boojack 51eac649c5 chore: update create tag dialog (#881) 2022-12-31 15:13:25 +08:00
boojack 7670c95360 chore: fix XSS in renderer (#880) 2022-12-31 11:52:57 +08:00
Ivan 65e9fdead1 feat: add russian locale (#879) 2022-12-31 09:02:14 +08:00
Zeng1998 2b2792de73 fix: logic of email validation (#877)
* fix: fix logic of email validation

* update
2022-12-30 13:10:52 +08:00
boojack c9bb2b785d chore: fix CSRF (#876) 2022-12-30 00:17:19 +08:00
boojack 64e5c343c5 chore: fix XSS in renderer (#875)
chore: fix xss in renderer
2022-12-29 23:27:56 +08:00
boojack 9169b3f2cd chore: update tip text for empty tag list (#872) 2022-12-29 09:14:24 +08:00
boojack b6f7a85a2a fix: reload page when sign out (#871) 2022-12-28 20:58:59 +08:00
boojack 3556ae4e65 fix: access control (#870) 2022-12-28 20:22:52 +08:00
boojack f888c62840 chore: update userinfo validator (#868)
* chore: update userinfo validator

* chore: update actions

* chore: update
2022-12-27 21:51:43 +08:00
Taras c160bed403 fead: add ukrainian locale (#864) 2022-12-26 19:10:47 +08:00
boojack afc9709484 chore: update dev config (#857) 2022-12-25 10:39:45 +08:00
boojack 05b41804e3 chore: hide host user email (#856) 2022-12-25 10:28:51 +08:00
Zeng1998 2e2657b39d feat: add setting for power editor (#851) 2022-12-24 16:18:13 +08:00
Zeng1998 60ee602639 feat: enable word break (#849)
* feat: enable word break

* Update web/src/less/editor.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update web/src/less/memo-content.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-24 14:50:27 +08:00
Zeng1998 cac04e4406 feat: enable word break (#849)
* feat: enable word break

* Update web/src/less/editor.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update web/src/less/memo-content.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-24 14:50:10 +08:00
M. Gschwandtner 278b4d21b4 fix: prioritize user css by moving it to the body end (#847)
Co-authored-by: M. Gschwandtner <84477901+OnlyPain-ctrl@users.noreply.github.com>
2022-12-24 09:35:30 +08:00
boojack 27fd1e2880 chore: remove secure flag (#848) 2022-12-24 08:31:37 +08:00
boojack fae9b3db46 chore: revert add linux/arm/v7 to platforms (#843)
Revert "chore: add `linux/arm/v7` to platforms (#842)"

This reverts commit 49c7f49820.
2022-12-23 22:39:04 +08:00
boojack 49c7f49820 chore: add linux/arm/v7 to platforms (#842) 2022-12-23 22:25:24 +08:00
boojack ef8981794e chore: restore dockerfile (#841) 2022-12-23 22:12:41 +08:00
boojack e52d77b2c4 chore: restore lockfile (#840) 2022-12-23 22:08:54 +08:00
boojack 1d2953b1b1 chore: downgrade joy-ui version (#839) 2022-12-23 21:53:13 +08:00
boojack d702eaa625 chore: update dockerfile (#838) 2022-12-23 20:48:51 +08:00
boojack 50811c3064 chore: update yarn.lock (#837) 2022-12-23 20:33:53 +08:00
boojack 99d9cc9168 fix: set csp header only for resource (#836) 2022-12-23 20:02:42 +08:00
boojack 119603da5d chore: upgrade version to 0.9.0 (#835) 2022-12-23 19:49:55 +08:00
boojack f6039f2eb9 chore: update dialog title (#834) 2022-12-23 19:49:44 +08:00
boojack 65cc19c12e chore: add escape to prevent XSS (#833) 2022-12-23 19:17:33 +08:00
boojack c07b4a57ca feat: add secure middleware (#832) 2022-12-23 18:58:55 +08:00
boojack dca35bde87 fix: disable decode patch id (#831) 2022-12-23 18:38:24 +08:00
boojack 9f25badde3 chore: update logo format to png (#830) 2022-12-23 00:21:53 +08:00
boojack 7efa749c66 feat: customize system profile (#828) 2022-12-22 19:48:44 +08:00
boojack 72daa4e1d6 feat: support heading syntax (#827) 2022-12-22 19:48:19 +08:00
ChasLui 54702db9ba feat: prevent page jitter caused by the presence of scroll bars (#808) 2022-12-22 17:46:09 +08:00
Zeng1998 41ad084489 fix: fix css of input placeholder in auth page (#824) 2022-12-22 17:45:12 +08:00
boojack 2fb171e069 chore: update create tag dialog style (#818)
* chore: update create tag dialog

* chore: update
2022-12-22 09:29:22 +08:00
boojack 201c0b020d chore: update seed data for tag (#817)
* chore: update seed data

* chore: add `_journal_mode` for SQLite

* chore: update create tag dialog
2022-12-22 08:34:05 +08:00
boojack b6f19ca093 feat: upsert tag based content (#816)
* feat: upsert tag based content

* chore: update
2022-12-22 00:35:47 +08:00
boojack 68a77b6e1f feat: create tag dialog (#814) 2022-12-21 23:59:03 +08:00
boojack e4a8a4d708 feat: tag table (#811)
* feat: tag table

* chore: update

* chore: update
2022-12-21 19:22:32 +08:00
boojack ab07c91d42 feat: update marked (#810) 2022-12-21 18:36:26 +08:00
ChasLui 1838e616fd feat: show active panel when searchBar is in focus (#806)
* feat: Show active panel when searchBar is in focus

* refactor: rename
2022-12-21 18:36:08 +08:00
M. Gschwandtner 90d0ccc2e8 feat: add arm/v7 to buildx platforms (#802)
added arm/v7 to buildx platforms

Co-authored-by: M. Gschwandtner <84477901+OnlyPain-ctrl@users.noreply.github.com>
2022-12-21 09:08:08 +08:00
ChasLui 358a5c0ed9 feat: press cmd+f to focus on the search bar (#800) 2022-12-21 00:46:22 +08:00
ChasLui 40f39fd66c feat: use shift+tab to unindent (#799)
* feat: Use shift+tab to unindent, just like vscode

* fix: shit+tab return
2022-12-20 23:03:25 +08:00
Jasper Platenburg 3b41976866 feat: implement plurals for stats (#783)
* implement plurals for stats

* renamed variables

* modified according to 18n guide
2022-12-20 21:29:10 +08:00
PublicHer0 a23de50bb8 feat: update spanish locale (#786)
* Adding spanish version

* update spanish locale

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-20 13:18:21 +00:00
Jasper Platenburg 6596e6893e feat: implement translation for days (#784)
implement trranslation for weekdays

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-20 13:10:25 +00:00
ChasLui b6fe4d914e fix: incorrect cursor when text is selected in range (#797) 2022-12-20 20:51:32 +08:00
ChasLui 3c2cd43d28 fix: shortcuts should exclude the shift judgment (#796)
* fix: Shortcuts should exclude the shift judgment

* fix: eslint
2022-12-20 19:47:35 +08:00
ChasLui 2658b1fd09 feat: support command + k shortcuts insert []() (#793)
* feat: support `command + k` shortcuts insert []()

* fix: eslint

* fix: clear code

* fix: eslint

* feat: insert [](url)

* refactor: rename param

* fix: eslint
2022-12-20 18:51:22 +08:00
Zeng1998 b7df1f5bbf feat: matching punctuation (#791) 2022-12-20 18:10:02 +08:00
ChasLui a0face6695 feat: update i18n (#790)
* feat: tag type i18n

* feat: custom server dialog i18n

* feat: i18n resources name

* feat: i18n toast

* fix: eslint

* eslint: fix

* fix: eslint

* fix: eslint
2022-12-20 17:47:02 +08:00
boojack c177db69d5 chore: update tag regexp (#785) 2022-12-20 09:44:41 +08:00
boojack b704c20809 chore: return raw text for html (#782) 2022-12-19 18:45:17 +08:00
boojack 6c17f94ef6 fix: max open conns for SQLite (#781) 2022-12-19 18:28:15 +08:00
lujiefsi 726285e634 chore: restrict the html file (#749)
* restrict the html file

* replace spaces with table

* remove space
2022-12-19 18:26:50 +08:00
Zeng1998 bd6ab71d41 chore: remove unused state (#780) 2022-12-19 18:03:39 +08:00
boojack b67ed1ee13 feat: customize system profile (#774)
* feat: system setting for customized profile

* chore: update

* feat: update frontend

* chore: update
2022-12-18 21:18:30 +08:00
Zeng1998 55695f2189 feat: esc key to exit multiple dialogs (#692)
* fix: `esc` key to exit multiple dialogs

* update

* update

* update

* Update web/src/components/Dialog/BaseDialog.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-18 10:09:12 +00:00
boojack e79d67d127 chore: update readme with deploy guides (#771) 2022-12-18 17:59:29 +08:00
ajstephens1995 1d9ef9813a docs: guide to deploy memos with render for beginners (#769) 2022-12-18 16:35:09 +08:00
boojack ef621a444f refactor: introducing use{Module}Store instead of service (#768)
* refactor: introducing `useEditorStore`

* refactor: update

* chore: update
2022-12-18 15:25:18 +08:00
boojack bd00fa798d chore: simplify ordered list in editor (#767)
chore: simplify editor
2022-12-18 12:44:46 +08:00
Zeng1998 a41745c9ae feat: editor enhancement for order list (#763) 2022-12-18 11:02:42 +08:00
M. Gschwandtner 1eec474007 fix: heatmap popup showing after logging out (#761)
* fix for heatmap popup showing after logging out

* moved node.remove to component unmount

* Update web/src/components/UsageHeatMap.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: M. Gschwandtner <84477901+OnlyPain-ctrl@users.noreply.github.com>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-17 03:10:06 +00:00
Stephen Zhou 83e5278b51 fix: dialog close when draging from in to out (#760) 2022-12-17 10:53:55 +08:00
boojack a8751af6b5 fix: memo list padding bottom (#759) 2022-12-17 10:19:15 +08:00
boojack 6b24f52cd1 fix: watermark container width (#758) 2022-12-17 10:15:54 +08:00
boojack 7ec22482c1 chore: upgrade version to 0.8.3 (#755) 2022-12-16 23:12:07 +08:00
boojack ee89dc00c0 chore: update list style (#754) 2022-12-16 23:09:01 +08:00
boojack bbd5fe4eb2 feat: remove sticky style for memo editor (#752) 2022-12-16 22:41:12 +08:00
boojack 575a0610a3 chore: revert "feat: add visibility field to resource (#743)" (#751)
Revert "feat: add `visibility` field to resource (#743)"

This reverts commit b68cc08592.
2022-12-16 22:20:17 +08:00
boojack b68cc08592 feat: add visibility field to resource (#743) 2022-12-15 21:15:16 +08:00
Stephen Zhou d51af7e98a fix: hr in edited content do not trigger folding (#748) 2022-12-15 18:38:35 +08:00
M. Gschwandtner 334da5e903 fix: add a span as wrapper to fix whitespace (#747) 2022-12-15 08:45:20 +08:00
Jasper Platenburg 35fed76d1a feat: add 'theme' to translation (#746) 2022-12-15 08:43:32 +08:00
boojack c77d49259a chore: update light bg color (#744) 2022-12-13 23:34:38 +08:00
PublicHer0 5520605ccc feat: add spanish locale (#741) 2022-12-13 09:12:22 +08:00
Zeng1998 1dee8ae49f fix: url resource filename decode (#738)
* fix: url resource filename decode

* update

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-12 20:00:21 +08:00
Zeng1998 3fd4ee83ac fix: checklist auto continuation (#737) 2022-12-12 18:30:04 +08:00
boojack 5e978e2cfc chore: update color scheme listener (#735) 2022-12-11 23:18:25 +08:00
boojack 37b7b983d2 chore: add vite plugin legacy (#734) 2022-12-11 22:15:52 +08:00
Zeng1998 c4278ef55a fix: fix order in resource dialog (#733) 2022-12-11 21:36:17 +08:00
Zeng1998 91220ea4a6 fix: reset image state in gallery (#730) 2022-12-11 20:14:55 +08:00
Zeng1998 4bebbf3e1d feat: enable paste multiple resources (#729)
* feat: enable paste multiple resources

* update

* update
2022-12-11 19:17:39 +08:00
boojack 5d8b8c37a5 chore: upgrade vite (#728)
* chore: upgrade vite

* Revert "chore: remove lazy import component (#724)"

This reverts commit 688dc2304c.
2022-12-11 18:38:29 +08:00
boojack 564f20d13a chore: remove ESC to close edit (#726) 2022-12-11 14:18:04 +08:00
boojack c3adb1b152 fix: set resource list in memo editor (#725) 2022-12-11 14:04:22 +08:00
boojack 688dc2304c chore: remove lazy import component (#724) 2022-12-10 19:39:43 +08:00
boojack dd6e2337e6 chore: update version to 0.8.2 (#722) 2022-12-10 13:23:38 +08:00
boojack 66418d4210 feat: get image only when cors error (#721) 2022-12-10 13:20:48 +08:00
boojack ab8c7b9d8a fix: auto complete in memo editor (#720) 2022-12-10 12:44:45 +08:00
M. Gschwandtner 387799b31c fix: added dark theme bg color to buttons (#719) 2022-12-10 12:14:02 +08:00
boojack 4a64a4dea8 fix: html lang attr (#718) 2022-12-10 10:42:10 +08:00
M. Gschwandtner 964c58ac01 feat: responsive layout for create shortcut dialog (#717) 2022-12-10 10:17:47 +08:00
boojack 56716cdad4 fix: break word (#708)
* fix: break word

* chore: update
2022-12-09 08:31:45 +08:00
Shruti Chaturvedi a2ee750d1e fix: bump Version of reusable.yaml (#707)
Bump version

Bump up the version for reusable.yaml to v2
2022-12-09 00:31:00 +08:00
Shruti Chaturvedi 3f0601f651 feat: add Uffizzi Integration (#655)
* Integrate Uffizzi

* Update docker-compose.uffizzi.yml

Start memos in dev mode

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-12-08 23:45:23 +08:00
Zeng1998 6f8e3432e9 fix: correct priority of keys in editor (#703) 2022-12-08 18:46:43 +08:00
Stephen Zhou b7ab6f8e7e fix: code highlight in dark mode (#702) 2022-12-08 18:30:46 +08:00
Zeng1998 36b92ad884 feat: auto continuation list in editor (#689)
* feat: auto continuation list in editor

* update

* update
2022-12-08 10:01:01 +08:00
apixandru 4d9857ce18 fix: update UsageHeatMap.tsx to account for daylight savings (#696) 2022-12-08 08:24:36 +08:00
boojack 43b22ce55f chore: fix typo (#695) 2022-12-07 22:49:05 +08:00
Zeng1998 147185309c feat: vacuum database in setting (#694)
* feat: vacuum database in setting

* update

* update

* update

* update
2022-12-07 22:45:47 +08:00
Maurice Bauer f48226d4f2 chore: update German translation (#691)
Switched to plural to make the difference between TAG(S) and TAG(E) visible...
Refers to #545
2022-12-07 20:18:35 +08:00
Zeng1998 e92407d9ec feat: image preview enhancement (#682) 2022-12-06 09:38:01 +08:00
Jasper Platenburg 79bf365d78 Dutch locale (#687) 2022-12-06 08:11:21 +08:00
Maurice Bauer 492a1370ab feat: add German i18n item (#686) 2022-12-06 07:42:17 +08:00
boojack e3ddf93c4d chore: update demo image (#672) 2022-12-04 20:43:46 +08:00
boojack 4a9314c476 chore: rename enableFoldMemo (#671)
* chore: rename `enableFoldMemo`

* chore: update
2022-12-04 15:34:03 +08:00
boojack 4767ee3293 feat: support follow system appearance (#670) 2022-12-04 12:23:29 +08:00
boojack 1ea74dfd0d chore: remove table syntax (#669) 2022-12-04 10:52:11 +08:00
Andreas Backström 53cf6ebb79 feat: add swedish/svenska translation (#668)
Add swedish / svenska translation
2022-12-03 21:38:25 +08:00
boojack d1007950e0 chore: remove emoji picker (#667) 2022-12-03 15:28:37 +08:00
Zeng1998 331226ec68 chore: fix some typos of README (#666) 2022-12-03 15:01:27 +08:00
boojack a7374cf998 fix: generate sharing memo image (#663) 2022-12-03 09:41:52 +08:00
boojack e3d76193b9 chore: update global css (#658) 2022-12-02 22:00:03 +08:00
boojack 07f0c3f052 chore: update global css (#657) 2022-12-02 21:34:43 +08:00
boojack a467a7c173 feat: upgrade dev version to 0.8.1 (#656)
* feat: upgrade version to `0.8.1`

* chore: update
2022-12-02 21:09:11 +08:00
boojack 14f9f29348 chore: update user setting appearance (#654) 2022-12-02 20:00:34 +08:00
EINDEX 5451fd2d2c feat: add a product of logseq plugin (#652) 2022-12-02 19:46:39 +08:00
hoi-lau f092771ea1 fix: resource-container overflow (#649) 2022-12-02 19:45:22 +08:00
boojack 7c6d7226f5 feat: update appearance selector (#645) 2022-12-01 20:57:19 +08:00
Stephen Zhou eaebc6dcef fix: apperance can not auto switch (#644) 2022-12-01 19:39:58 +08:00
boojack c5200ca31b feat: dark mode for dialogs (#643) 2022-11-30 20:34:16 +08:00
Tiefseemonster 1078132b12 fix: member menu dropdown position (#639)
* fix: member menu dropdown position

* chore: cleanup

* chore: cleanup
2022-11-30 20:18:39 +08:00
Stephen Zhou 6b058cd299 feat: save folding option with localstorage (#641)
* fix: change folding option need reload

* fix: floding option undefied
2022-11-30 19:13:55 +08:00
Wence b8f24af5ae feat: dynamic lazy loading route with simple loading page (#632)
* feat: dynamic loading route with simple loading page

* fix: lint fix

* Update web/src/less/loading.less

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-29 22:13:22 +00:00
boojack 6384f5af74 feat: dark mode for main pages (#637)
* feat: update dark mode styles for auth and explore page

* feat: dark mode for home page
2022-11-29 21:44:52 +08:00
Zeng1998 52038d26d2 chore: update i18n for validator message (#636) 2022-11-29 21:35:40 +08:00
boojack 55f37664ef chore: add theme file for joyui (#635) 2022-11-29 20:15:16 +08:00
Zeng1998 ab8e3473a1 feat: support resources reuse (#620)
* feat: support resource reuse

* update

* update

* update

* update
2022-11-29 19:07:20 +08:00
Zeng1998 eba23c4f6e fix: add validation for user information update (#633) 2022-11-29 19:03:29 +08:00
Zeng1998 00fe6d3862 chore: add joyui tooltip for resources dialog (#630) 2022-11-29 09:36:48 +08:00
Charles Chin 3646b8f5dd docs: update readme (#628) 2022-11-29 06:34:44 +08:00
boojack d40639bf8e chore: update readme me with contributors graph (#626) 2022-11-28 22:48:02 +08:00
Zeng1998 12b81781b9 feat: share memo dialog (#618)
* feat: new share dialog

* update

* update

* update

* update
2022-11-28 21:20:35 +08:00
Zeng1998 b67a37453d feat: member management enhancement (#617)
* feat: member management enhancement

* update

* update

* update

* update
2022-11-28 19:59:11 +08:00
boojack b04e001db1 fix: image url host missing (#623) 2022-11-28 19:52:03 +08:00
Stephen Zhou fbe7b604ef feat: dark mode support for memo detail (#604)
* feat: dark mode support for memo detail

* chore: update

* chore: update

* chore: update
2022-11-28 19:40:08 +08:00
Zeng1998 0402cb7b27 fix: no user settings returns when patch user (#622) 2022-11-28 19:38:44 +08:00
Tiefseemonster b72bfc9c24 fix: selector dropdown position in fullscreen mod (#619) 2022-11-28 19:36:42 +08:00
Zeng1998 40e92f9463 fix: change password max length validation (#616) 2022-11-28 19:33:14 +08:00
Zeng1998 f883dd9c1d feat: create user repeat password (#614)
* feat: create user repeat password

* update
2022-11-28 19:32:53 +08:00
Wujiao233 d8bf55efb2 fix: shoutcut tag filter handle mutiple tags (#608)
* fix: shoutcut tag filter handle mutiple tags

* not edit parser
2022-11-28 19:32:01 +08:00
Wujiao233 f982e83d0a fix: clear shortcut filter when delete this shortcut (#611) 2022-11-28 06:14:25 +08:00
Jasper Platenburg 3472a6db26 fix: password field visible (#609) 2022-11-27 21:53:10 +08:00
boojack c79e51a91b chore: update readme (#606) 2022-11-27 16:04:35 +08:00
boojack ce795a2a7d chore: show content image (#602) 2022-11-27 09:01:19 +08:00
boojack 045819c312 fix: initial database schema (#601) 2022-11-27 08:52:43 +08:00
Tiefseemonster 2fa01886da fix: tooltip overlaps a window border (#599) 2022-11-27 08:48:21 +08:00
Tiefseemonster dd7d322c47 chore: add .vscode to gitignore (#596) 2022-11-27 07:56:19 +08:00
Tiefseemonster dfe71f33c2 fix: search bar dropdown disappearing (#593) 2022-11-26 23:13:02 +08:00
boojack db1d223448 fix: apperance select (#585) 2022-11-26 17:45:16 +08:00
Zeng1998 54271c1598 chore: fix some typos (#587) 2022-11-26 06:23:29 +00:00
Zeng1998 1ee8ebc9e1 fix: collapse btn cursor style (#586) 2022-11-26 05:12:37 +00:00
Stephen Zhou 6e5537d131 feat: dark mode support for explore page (#584)
* feat: dark mode support for auth page

* chore: update

* feat: dark mode support for explore page (#583)

* fix: avoid white text

* fix: import order
2022-11-26 12:19:00 +08:00
Stephen Zhou 90c85103c3 feat: dark mode support for auth page (#569)
* feat: dark mode support for auth page

* chore: update
2022-11-26 11:20:22 +08:00
Zeng1998 2d5d734da4 chore: update i18n for account settings (#582) 2022-11-26 02:23:57 +00:00
Zeng1998 e1e5121dd7 fix: get markdown image from backend (#581) 2022-11-26 10:20:49 +08:00
boojack 85db6721de chore: disable metrics collector (#580) 2022-11-26 09:23:38 +08:00
boojack b511a7b634 fix: user patch with empty email (#578) 2022-11-25 22:34:24 +08:00
boojack 88c3b1ad0f feat: update prod version (#577) 2022-11-25 22:17:24 +08:00
boojack 9fe15a03b3 chore(revert): update test image platforms (#576)
Revert "chore: update test image platforms (#575)"

This reverts commit 500afffbcf.
2022-11-25 22:08:43 +08:00
boojack 500afffbcf chore: update test image platforms (#575)
chore: update test image plantforms
2022-11-25 22:06:40 +08:00
Zeng1998 5f3cade810 feat: highlight the searched text in memo content (#514)
* feat: highlight the searched text in memo content

* update

* update

* update

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-25 21:59:21 +08:00
boojack 072851e3ba chore: update dialog style (#574)
* chore: update tests

* chore: update dialog styles
2022-11-25 21:55:45 +08:00
boojack e2cbea2022 chore: update action name (#573) 2022-11-25 21:53:36 +08:00
boojack 29880be283 chore: update tests (#572) 2022-11-25 21:51:53 +08:00
Tiefseemonster f4e2b7319a fix: make tooltip text no-selecting (#567)
* no selecting tooltip text

With a double click on button, you can get selection on tooltip text. That may be distracting a little bit.

* Update web/src/less/memo.less

Co-authored-by: Stephen Zhou <hi@hyoban.cc>

Co-authored-by: Stephen Zhou <hi@hyoban.cc>
Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-25 20:32:59 +08:00
Zeng1998 ff0db82dc3 chore: empty query text (#566) 2022-11-25 20:09:42 +08:00
Stephen Zhou 2daf085ce4 chore: fix vscode settings name (#565) 2022-11-25 01:51:43 +00:00
Tiefseemonster 495f1f2041 chore: fix name field in paragraph parser obj (#564) 2022-11-25 01:47:17 +00:00
boojack 89179f78c2 chore: add SECURITY.md (#562) 2022-11-25 09:05:52 +08:00
boojack 7ad7461a92 chore: add test docker image (#559) 2022-11-24 20:54:22 +08:00
boojack 8cfcd201b0 feat: support display video (#558) 2022-11-24 20:22:54 +08:00
boojack abcd3cfafb feat: add Strikethrough syntax (#557)
feat: add `Strikethrough` rule
2022-11-24 20:05:51 +08:00
boojack 50d41c456b chore: change memo created time (#556) 2022-11-24 19:55:52 +08:00
Zeng1998 1d41d53723 fix: icon style (#555) 2022-11-24 18:44:47 +08:00
boojack 0dc003854f chore: fix typo (#551) 2022-11-24 10:03:00 +08:00
Zeng1998 a4b7a77016 fix: cursor style (#549) 2022-11-24 09:30:17 +08:00
boojack 939e836d1b chore: update readme (#548) 2022-11-24 08:45:36 +08:00
boojack a0b35f7aa9 feat: add French i18n item (#547)
feat: add French i18n
2022-11-24 08:42:38 +08:00
baptiste313 574e160a11 chore: addition of the French translation and small correction for the English (#546) 2022-11-24 08:03:16 +08:00
boojack 2042737004 feat: add username field (#544)
* feat: add username field

* chore: update
2022-11-23 22:27:21 +08:00
boojack a0667abec8 chore: update data initial requests (#538) 2022-11-22 23:45:11 +08:00
boojack 362306a9cb chore: update i18n for visibility (#537) 2022-11-22 22:59:54 +08:00
Zeng1998 5e069f79a2 feat: esc to cancel editing (#532) 2022-11-22 19:54:25 +08:00
Zeng1998 7c78fb064f fix: empty filter value (#529) 2022-11-22 11:31:37 +00:00
Zeng1998 11a7e897dc fix: update issue template (#530) 2022-11-22 19:30:04 +08:00
Yarden Shoham d8adc0afe9 feat: extend validation config max length (#523) 2022-11-22 18:21:12 +08:00
boojack 17c1b97d23 fix: tag regexp (#518)
* fix: tag regexp

* chore: update
2022-11-21 23:49:52 +08:00
boojack 5aee2f46ab chore: update issue template (#517) 2022-11-21 23:38:21 +08:00
boojack 013ded1e04 chore: code clean (#516) 2022-11-21 23:23:05 +08:00
Zeng1998 0d0f893b93 chore: update i18 for memo sharing (#513) 2022-11-21 19:59:19 +08:00
Zeng1998 d2a87a4ddb chore: bgcolor of memo share image (#508) 2022-11-21 18:38:32 +08:00
boojack b05a176490 chore: add license to README (#506) 2022-11-21 07:20:36 +08:00
boojack d149926a39 chore: update seed data (#507) 2022-11-21 07:17:28 +08:00
boojack 2d49e96a8a feat: get image blob in backend (#495)
* feat: get image blob in backend

* chore: update
2022-11-19 18:43:56 +08:00
boojack 9036bd478b fix: image scrollbar (#494) 2022-11-19 17:36:25 +08:00
boojack 477130aa85 chore: update db filesize access control (#493) 2022-11-19 17:07:40 +08:00
boojack 878e0eabc8 feat: add crawler plugin (#492)
* feat: add crawler plugin

* chore: update

* chore: go mod tidy

* chore: update
2022-11-19 16:58:55 +08:00
boojack 62f63d4af7 chore: update dependencies version (#491) 2022-11-19 14:51:28 +08:00
Zeng1998 1acf2f8b13 chore: update i18 for settings (#490) 2022-11-19 10:33:52 +08:00
boojack a4a5e539ed chore: update dev version (#489) 2022-11-19 09:57:54 +08:00
boojack a2831b37c4 feat: add database filesize in UI (#488) 2022-11-18 21:17:52 +08:00
boojack 706b1b428f chore: add toast to system settings (#486) 2022-11-17 21:37:57 +08:00
boojack 1690566413 chore: update emoji picker (#483) 2022-11-17 21:11:58 +08:00
boojack a24b885236 chore: update share memo image (#482) 2022-11-17 21:01:26 +08:00
Stephen Zhou c89a6665b6 feat: fold memos according to horizontal rule (#478)
* feat: fold memos according to horizontal rule

* fix: button and content

* chore: update
2022-11-15 14:49:08 +00:00
Stephen Zhou 797accbc2c feat: parser for horizontal rule (#477)
* feat: parser for horizontal rule

* chore: revert
2022-11-15 21:56:44 +08:00
boojack 66f9bc48bb chore: remove mark memo (#476) 2022-11-15 21:22:08 +08:00
boojack de2eff474c chore: remove memo card dialog (#475) 2022-11-15 21:16:53 +08:00
Mahoo Huang 67195859dc fix: abnormal link regex (#474) 2022-11-15 21:15:10 +08:00
boojack 61abc6dd11 feat: update sharing memo image (#473) 2022-11-15 21:02:55 +08:00
boojack 9fe9245727 chore: update cancel edit button style (#472) 2022-11-15 20:35:56 +08:00
Zeng1998 906ec7994e fix: clear query text (#469)
* fix: clear query text

* update

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-15 19:52:16 +08:00
Zeng1998 5258b0a5b4 chore: change memo card's bg color (#471) 2022-11-15 18:55:11 +08:00
boojack ceac53b6d0 feat: additional script system setting (#467) 2022-11-14 22:21:19 +08:00
Stephen Zhou 3775d5c9c2 feat: folding options (#459)
* feat: folding options

* chore: update

* chore: update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-14 22:06:05 +08:00
Zeng1998 da80d4ef62 fix: duration query string (#465) 2022-11-14 18:57:43 +08:00
Stephen Zhou 205ad0fd6d chore: change rss item title (#464) 2022-11-14 13:28:50 +08:00
Zeng1998 d208731f5f feat: visibility click filter (#463)
* feat: visibility click filter

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-13 21:23:40 +08:00
Stephen Zhou a90acdabb3 fix: route confusion entering from non-home page (#460)
Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-13 19:40:16 +08:00
Zeng1998 407d1cdcaa feat: add visibility filter (#461)
* feat: add visibility filter

* update
2022-11-13 19:34:22 +08:00
boojack cb50bbc3cb refactor: remove mixin colors (#458) 2022-11-13 14:25:02 +08:00
boojack 2743268fd7 chore: remove unused visibility selector (#457) 2022-11-13 10:47:21 +08:00
Zeng1998 8cc0977a01 fix: image url extraction (#453)
fix: image-url-extraction

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-12 21:25:50 +08:00
boojack 0809ec8c72 chore: update editor style (#456) 2022-11-12 21:22:51 +08:00
boojack db93710f85 chore: remove mobile editor style user setting (#455) 2022-11-12 21:01:34 +08:00
boojack 241c93c6b7 feat: update editor style (#454)
* feat: update editor style

* chore: update bg
2022-11-12 20:57:08 +08:00
boojack bf07ab9e2f fix: remove duplicate tag (#450)
fix: remove dumplicate tag
2022-11-12 11:31:16 +08:00
boojack fe05e6a464 chore: update version 0.7.2 (#447) 2022-11-12 09:19:44 +08:00
boojack d1aa6aa7f8 fix: editor resource list (#445) 2022-11-12 09:04:26 +08:00
boojack 79af7e8abf fix: parse tag list (#446) 2022-11-12 09:02:44 +08:00
boojack a142d975d7 feat: additional style system setting (#444)
* feat: additional style system setting

* feat: remove editor font setting
2022-11-11 23:42:44 +08:00
boojack 67691d1e99 feat: update visibility selector style (#441) 2022-11-11 19:25:21 +08:00
Zeng1998 9b827b4801 feat: add support for time-shortcut (#434)
* feat: add support for time-shortcut

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-11 19:14:38 +08:00
Zeng1998 421f4dbf60 feat: select visibility in editor (#421)
* feat: editing visibility selection

* update

* update

* update variable name

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-10 13:43:49 +00:00
boojack 8f119c4265 chore: update session key (#440) 2022-11-10 20:51:37 +08:00
boojack 9866702850 fix: parser regexp for special character (#439) 2022-11-10 20:38:14 +08:00
Yunliang Zhou a313a9bb31 fix: route confusion entering from non-home page (#430) 2022-11-10 19:50:12 +08:00
boojack e53f5fdd29 chore: update seed data (#437) 2022-11-10 08:41:11 +08:00
Zeng1998 b6c0a04394 fix: share memo with resource list (#431)
* fix: share memo with resource list

* update

* Update web/src/components/ShareMemoImageDialog.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-09 14:58:16 +00:00
Zeng1998 1e3b8315a0 chore: update MemoResources props (#432) 2022-11-09 22:10:31 +08:00
boojack dc5d705f8c feat: vacuum records manually (#420) 2022-11-06 04:21:58 +00:00
Zeng1998 4f10c12092 chore: update translation (#417) 2022-11-05 21:55:48 +08:00
Zeng1998 3aa44f9f6d fix: delete related resources (#415)
* chore: add icon

* fix: delete all related resources when a memo is deleted

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-05 20:21:13 +08:00
Zeng1998 78b4733fb9 chore: add icon for deleting resource (#414) 2022-11-05 17:41:14 +08:00
winwin2011 37bb3bc546 chore: allow skip version (#411)
* chore: allow skip version

* chore: opacity

* chore: polish

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-04 15:40:48 +00:00
winwin2011 b43bfce254 fix: tag compressed (#412) 2022-11-04 23:39:20 +08:00
boojack 0d6281ef6b chore: update signin page (#410)
* chore: update signin page

* chore: update version `v0.7.1`
2022-11-04 12:28:16 +00:00
boojack 8e2844e0c5 fix: tag regexp (#409)
* chore: enable `no-unused-vars`

* fix: tag regexp
2022-11-04 00:28:29 +00:00
boojack c27e38b11c chore: enable no-unused-vars (#408) 2022-11-03 23:43:56 +00:00
boojack cf75054106 feat: add system setting to allow user signup (#407) 2022-11-03 21:47:36 +08:00
Zhou Yunliang 4ed987229b feat: text filter regex support (#406) 2022-11-03 21:06:17 +08:00
Mahoo Huang a1068b6fe3 fix: abnormal blockquote regexp (#404)
```markdown
面向具体实现编程 ==> 面向抽象接口编程
```.
面向具体实现编程 ==
> 面向抽象接口编程
2022-11-02 20:33:25 +08:00
Zhou Yunliang 91a61e058a feat: view all images of a memo (#393)
* feat: view all images of a memo

* fix: function arguments

* refactor: unified image preview

* refactor: image preview for resource dialog

Co-authored-by: XQ <qiaobingxue1998@163.com>
2022-11-02 12:00:28 +00:00
Zhou Yunliang bebcabc292 chore: update gitignore (#402) 2022-11-02 18:57:45 +08:00
winwin2011 5bdf15aece chore: fold/expand i18n (#400) 2022-11-01 22:44:23 +00:00
winwin2011 d347b7a91e chore: pin button color (#399) 2022-11-02 06:42:20 +08:00
boojack 2c653f170c chore: update corner width (#398) 2022-11-01 15:13:54 +00:00
boojack 75218ef826 chore: update readme (#397) 2022-11-01 15:09:17 +00:00
boojack b7fbbed895 chore: update pagination for getting all memos (#396) 2022-11-01 14:57:33 +00:00
boojack f8c0d73d2d chore: update resource dialog style (#395) 2022-11-01 14:24:54 +00:00
boojack 006cb56d28 fix: heatmap data (#394) 2022-11-01 14:06:02 +00:00
boojack 55dee0df7e fix: session max age (#392) 2022-11-01 13:03:33 +00:00
boojack 2a275b2875 fix: memo list default value (#390) 2022-11-01 09:12:00 +08:00
Zeng1998 4246232fbe feat: image preview enhancement (#385)
* feat: dialog content enhancement

* update

* feat: image carousel

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-11-01 09:07:14 +08:00
boojack 9d8c9609c3 feat: cache editing memo id (#388)
* feat: cache editing memo id

* chore: update
2022-10-31 21:39:22 +08:00
boojack ef5492074e chore: update memo stats api (#387) 2022-10-31 20:57:07 +08:00
boojack 40d5686031 chore: update unpin memo (#386) 2022-10-31 11:27:56 +00:00
Zeng1998 4276a7a56d feat: remove unused resources (#379)
* feat: dialog content enhancement

* feat: remove unused resources

* update

* update

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-31 11:23:44 +00:00
Zeng1998 d6fa1c7c80 feat: dialog content enhancement (#377) 2022-10-31 11:00:18 +00:00
boojack 6cbc3c78e2 chore: update readme (#375) 2022-10-30 14:42:56 +08:00
boojack 29966451b6 feat: unpin button in the corner (#374)
* feat: unpin button in corner

* chore: update
2022-10-30 05:21:24 +00:00
boojack 64f0662a61 fix: get memo list order (#370) 2022-10-29 12:54:54 +00:00
boojack 0ccfd0c743 fix: resource table migration (#369)
* fix: resource table migration

* chore: update
2022-10-29 11:47:31 +00:00
boojack 0ea1733acc fix: missing column in resource table (#368) 2022-10-29 10:49:58 +00:00
boojack 8fb59bbfb9 chore: release v0.7.0 (#367)
chore: update release version
2022-10-29 10:18:24 +00:00
boojack 7c401040c8 feat: add blockquote regexp (#366) 2022-10-29 10:14:53 +00:00
boojack 43541bde2c feat: add update version banner (#365)
feat: add update version banenr
2022-10-29 09:49:50 +00:00
boojack 1e01c4dc46 chore: update resource service (#364) 2022-10-29 09:24:56 +00:00
Zeng1998 e85d368f87 feat: patch resource filename (#360)
* feat: resource filename rename

* update: resource filename rename

* update: resource filename rename

* update: validation about the filename

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-29 07:40:09 +00:00
boojack 95376f78f6 feat: add metric plugin (#361) 2022-10-29 03:15:39 +00:00
Zeng1998 30daea0c4f fix: typo (#357)
* feat: resource dialog enhancements

* update

* fix: typo

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-29 01:13:11 +00:00
Zeng1998 b891e08928 feat: resource dialog enhancements (#356)
* feat: resource dialog enhancements

* update
2022-10-29 09:11:16 +08:00
boojack 94df09c8c0 chore: update memo list api (#350) 2022-10-27 14:02:42 +00:00
boojack bdf6d4d42a feat: case-insensitive search (#347) 2022-10-27 00:05:45 +00:00
boojack cb2e1ae355 fix: fetch memo with filter (#346) 2022-10-26 23:53:40 +00:00
boojack 9705406b82 feat: remove foreign key and triggers (#345) 2022-10-26 15:00:09 +00:00
Zhou Yunliang 4e00b1b0cd feat: rss support (#343)
* feat: rss support

* chore: go mod tidy

* chore: change route group prefix

* Update server/server.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

* Update server/rss.go

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-26 20:13:02 +08:00
boojack fe5ba6850b chore: update insert content in editor (#336) 2022-10-23 12:28:30 +00:00
Mahoo Huang 5690dab6bb feat: add some hotkeys (#320)
* feat: add some hotkeys

* fix: hotkeys lose the text behind selected

* chore: adjust insertText params passing
2022-10-23 11:33:45 +00:00
Zeng1998 65506a5b30 chore: update the translation (#333) 2022-10-22 09:36:38 +00:00
boojack f09bb2689c chore: release v0.6.1 (#332) 2022-10-21 15:21:37 +00:00
boojack e6f376ae66 fix: user setting name (#331) 2022-10-21 15:06:15 +00:00
boojack 1c2998c4d8 feat: pagination for memo list (#330) 2022-10-21 14:51:41 +00:00
Zeng1998 fc5d5cf231 fix: patch memo with resource list (#328)
fix: 修改memo时添加图片不显示
2022-10-21 22:16:05 +08:00
boojack 2a4fc7dcc3 chore: update memo display time (#327)
* chore: update memo display time

* chore: update
2022-10-21 20:26:00 +08:00
boojack b68d6e2693 feat: update memo sort option setting (#326)
feat: add memo display ts
2022-10-21 11:57:57 +00:00
boojack 0b34b142c8 chore: update marked (#325) 2022-10-21 09:13:19 +08:00
boojack 0b2a9d8511 fix: bold and emphasis regex (#323)
* fix: bold and emphasis regex

* chore: udpate
2022-10-20 21:57:40 +08:00
winwin2011 7c9c5c316b chore: update i18n in settings (#324)
chore: i18n
2022-10-20 21:40:03 +08:00
winwin2011 180ae206c7 feat: inline code within link (#321)
* feat: inline code with link

* fix: decoration style
2022-10-20 21:21:30 +08:00
boojack 69e3ba6bed chore: update demo seeding data (#318)
chore: update seeding data
2022-10-20 17:19:37 +08:00
Zeng1998 bf5b7e747d feat: customize memo list sorting rules (#312)
* chore: update .gitignore

* feat: 添加Memo列表按更新时间排序

* fix go-static-checks

* update

* update

* update Memo.tsx/MemoList.tsx

* handle conflict

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-19 21:00:34 +08:00
f97 24154c95f2 feat: editor tab support (#309)
* feat: editor tab support

* Update web/src/components/MemoEditor.tsx

Co-authored-by: boojack <stevenlgtm@gmail.com>

* chore: if return style

Co-authored-by: boojack <stevenlgtm@gmail.com>
Co-authored-by: hyoban <hi@hyoban.cc>
2022-10-19 18:19:50 +08:00
boojack 0b10d24eb2 chore: update bug report template (#316)
chore: update but report template
2022-10-19 08:22:56 +08:00
boojack 06ec59eca4 chore: add issue template (#314) 2022-10-18 23:13:41 +08:00
boojack 35a8817442 fix: memo list auto scroll to top (#313)
fix: editor initial content
2022-10-18 22:56:43 +08:00
boojack c7378e78d9 chore: update mask animation styles (#306) 2022-10-17 18:43:02 +08:00
Tiger ab182dc22a chore: update zh.json (#304)
Update zh.json
2022-10-16 13:49:58 +08:00
boojack f554e5a357 fix: close button z-index in setting dialog (#303) 2022-10-16 12:37:17 +08:00
Steven 749486ba3c chore: update marked tests 2022-10-15 21:57:56 +08:00
Hyoban 26aae0e637 fix: blank line after table (#298) 2022-10-15 17:51:17 +08:00
Hyoban 95c8d8fc9c docs: update docker-compose tip (#299) 2022-10-15 15:32:42 +08:00
Hyoban 1021023577 docs: docker compose tip (#296)
* docs: docker compose tip

* chore: update

Co-authored-by: boojack <stevenlgtm@gmail.com>

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-15 13:27:06 +08:00
Hyoban 3d0c6004c0 feat: support markdown table (#294)
* feat: support markdown table

* chore: update table style

* test: for markdown table parse
2022-10-15 11:42:04 +08:00
Steven 6c53bd00f6 chore: restore user email 2022-10-15 11:27:12 +08:00
Steven cc759bef56 fix: handle highlight unknown language error 2022-10-15 06:11:17 +08:00
Steven d670adc11f chore: release v0.6.0 2022-10-14 23:25:07 +08:00
Steven 349c383604 chore: reorder memo resource 2022-10-14 23:14:08 +08:00
Steven f407488128 chore: update dev version 2022-10-14 23:03:54 +08:00
boojack 086b10717f feat: upload files by dropping (#292) 2022-10-14 22:59:30 +08:00
boojack eefd0444c8 feat: add highlight for code block (#291)
* feat: add highlight for code block

* chore: update test
2022-10-14 22:29:28 +08:00
Hyoban 65a61ed270 fix: can not click sidebar (#289) 2022-10-14 21:43:43 +08:00
Hyoban 5e7db4631e feat: handle esc keyboard event for editor (#288) 2022-10-14 10:14:35 +08:00
boojack 0d6114e25e feat: update sidebar mask styles (#287) 2022-10-14 07:26:43 +08:00
h2o2o ce5a6fa3ac chore: update sidebar styles in mobile view (#285)
* 添加移动端点击自动关闭侧边栏

* 添加移动端点击自动关闭侧边栏

* 添加移动端点击自动关闭侧边栏

* move closeSidebar function to utils

* move closeSidebar function to utils

* 侧边栏优化

* 移动端侧边栏优化

* 移动端侧边栏优化

* 移动端侧边栏优化
2022-10-13 22:56:42 +08:00
boojack 246851fdbe fix: create memo with visibility (#281) 2022-10-13 09:01:09 +08:00
boojack 21c30ac157 chore: hide user email (#282) 2022-10-13 09:01:02 +08:00
Steven 269d92e637 fix: create triggers after dropping old tables 2022-10-13 08:23:05 +08:00
Steven ffe145d436 chore: revert sidebar updates 2022-10-13 08:05:59 +08:00
zburu 37cd841992 chore: adjust sidebar style (#277) 2022-10-13 07:54:34 +08:00
h2o2o 315ab94c94 添加移动端点击自动关闭侧边栏 (#271) 2022-10-11 08:12:35 +08:00
f97 1aa9963e07 fix: i18n for filter (#275) 2022-10-10 17:46:52 +08:00
Steven 88ade2c0b7 chore: update i18n for filter 2022-10-09 08:54:05 +08:00
winwin2011 4ada7dce77 chore: update i18n for shortcut filter (#270)
* chore: resources i18n

* chore: shortcut-list i18n

* chore: resources i18n

* chore: resources i18n

* chore: resources i18n
2022-10-08 22:27:23 +08:00
steven a323689ee6 chore: update copy button style 2022-10-05 20:55:04 +08:00
f97 2ea612e2fe feat: add copy button to memo (#267)
* feat: copy-content

* Update web/src/less/memo-detail.less

Co-authored-by: boojack <stevenlgtm@gmail.com>
2022-10-05 16:39:04 +08:00
boojack ca2557eb7e fix: tag filter (#266) 2022-10-04 21:02:07 +08:00
steven e0f95686f3 chore: update header style 2022-10-04 20:42:33 +08:00
f97 29770e8bfb chore: update vietnamese i18n (#261) 2022-10-04 14:37:44 +08:00
steven b959acc69d fix: update marked test cases 2022-10-04 14:35:07 +08:00
steven 486cf8bdac feat: add escape to renderer 2022-10-04 13:53:36 +08:00
steven ea911387f1 chore: update migration sql file 2022-10-04 12:04:26 +08:00
steven 0b9b89db81 chore: update VACUUM 2022-10-04 10:48:45 +08:00
boojack eaf89aa2f2 feat: update marked parsers (#260)
* chore: remove external match functions

* chore: update parsers
2022-10-04 10:44:16 +08:00
boojack 4bd373ba57 fix: tag selector position (#259) 2022-10-04 08:48:43 +08:00
steven 7b29c65f58 feat: add inline-code syntax parser 2022-10-03 19:51:54 +08:00
steven 2298ac6ff3 chore: add FUNDING.yml 2022-10-03 19:43:56 +08:00
steven 4477f47c25 chore: release version 0.5.0 2022-10-03 18:49:11 +08:00
steven 4a2fe3aaae chore: update user banner style 2022-10-03 18:48:44 +08:00
steven 0f65b8bdd3 fix: re-generate table columns foreign keys 2022-10-03 18:47:31 +08:00
steven 778282ae29 chore: update resource dialog 2022-10-03 09:39:59 +08:00
steven 85dc29bfb9 feat: add linkedMemoAmount to resource 2022-10-03 09:39:49 +08:00
steven 05e46ee4a8 fix: emoji picker style 2022-10-03 09:11:07 +08:00
steven 6a3b052fa2 chore: don't clean data in dev mode 2022-10-03 08:49:20 +08:00
boojack 222c792539 fix: tag regexp (#253) 2022-10-02 23:12:06 +08:00
boojack 51fb8ddb07 feat: simple markdown parser (#252)
* feat: simple markdown parser

* chore: rename test file name

* feat: add plain text link parser

* chore: update style
2022-10-02 22:49:30 +08:00
steven 8e63b8f289 chore: update interval flag type 2022-10-01 23:01:32 +08:00
steven 17c35be426 chore: add --passWithNoTests to jest 2022-10-01 22:59:00 +08:00
steven dfd461518f chore: add jest github action 2022-10-01 22:57:32 +08:00
steven df5818cdc5 chore: add jest 2022-10-01 22:56:20 +08:00
steven 5894104524 chore: update inline image 2022-10-01 20:00:45 +08:00
steven 09732df0f5 chore: regenerate yarn.lock 2022-10-01 19:59:15 +08:00
steven ae8f292306 feat: create memo with resourceIdList 2022-10-01 10:57:14 +08:00
steven 9f8c0ce567 fix: raw data cache 2022-10-01 10:37:02 +08:00
steven c7cf35c7de feat: update memo resource component 2022-10-01 10:02:16 +08:00
steven e5c9d8604d feat: compose memo resource list 2022-10-01 09:49:59 +08:00
steven b2c22977c1 feat: update memo editor with uploading resources 2022-10-01 00:10:31 +08:00
steven c0edb72b3d chore: update react version 2022-10-01 00:07:06 +08:00
steven 33d31b7dca fix: delete memo resource 2022-10-01 00:06:56 +08:00
steven 4c465bef2d feat: add memo resource apis 2022-09-30 22:58:59 +08:00
steven 3bde9543f3 chore: update dev version v0.5.0 2022-09-30 22:58:12 +08:00
steven cff0e86989 feat: add memo_resource model 2022-09-30 20:20:00 +08:00
boojack 65f7aa7914 fix: emoji picker position in fullscreen (#251) 2022-09-30 18:40:46 +08:00
boojack 06f5a5788e fix: mobile editor float style (#247) 2022-09-27 22:58:03 +08:00
boojack 52c8ac2ad3 chore: update emoji picker toggle logic (#244) 2022-09-26 22:33:41 +08:00
Steven 0c80654cc2 chore: update dropdown action button style 2022-09-26 22:06:06 +08:00
Steven a2180f177f chore: remove vite-plugin-pwa 2022-09-26 21:40:37 +08:00
Steven b992d07f3e chore: update memo detail header 2022-09-24 10:05:51 +08:00
915 changed files with 120606 additions and 19683 deletions
+12 -1
View File
@@ -1,2 +1,13 @@
web/node_modules
web/yarn.lock
web/dist
.git
.github
build/
tmp/
memos
*.md
.gitignore
.golangci.yaml
.dockerignore
docs/
.DS_Store
+1
View File
@@ -0,0 +1 @@
github: usememos
+82
View File
@@ -0,0 +1,82 @@
name: Bug Report
description: If something isn't working as expected
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to report a bug! Please complete the form below to help us understand and fix the issue.
- type: checkboxes
id: pre-check
attributes:
label: Pre-submission Checklist
description: Please confirm you have completed the following steps before submitting
options:
- label: I have searched the existing issues and this bug has not been reported yet
required: true
- label: I have tested this issue on the [demo site](https://demo.usememos.com) or the latest version
required: true
- type: dropdown
id: issue-location
attributes:
label: Where did you encounter this bug?
description: Select where you tested and confirmed this issue
options:
- Latest stable version (self-hosted)
- Latest development version (self-hosted)
- Demo site (demo.usememos.com)
- Older version (please specify below)
default: 0
validations:
required: true
- type: input
id: version
attributes:
label: Memos Version
description: Provide the exact version (e.g., `v0.25.2`). Find this in Settings → About or via `--version` flag
placeholder: v0.25.2
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Bug Description
description: A clear and concise description of what the bug is
placeholder: When I try to..., the application...
validations:
required: true
- type: textarea
id: reproduction-steps
attributes:
label: Steps to Reproduce
description: Detailed steps to reproduce the behavior
placeholder: |
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. See error
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: What did you expect to happen?
placeholder: I expected...
- type: textarea
id: additional-context
attributes:
label: Screenshots & Additional Context
description: Add screenshots, browser/OS info, deployment method (Docker/binary), or any other relevant details
placeholder: |
- Browser: Chrome 120
- OS: macOS 14
- Deployment: Docker
- Database: SQLite
+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: false
@@ -0,0 +1,76 @@
name: Feature Request
description: If you have a suggestion for a new feature
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Thank you for suggesting a new feature! Please complete the form below to help us understand your idea.
- type: checkboxes
id: pre-check
attributes:
label: Pre-submission Checklist
description: Please confirm you have completed the following steps before submitting
options:
- label: I have searched the existing issues and this feature has not been requested yet
required: true
- type: dropdown
id: feature-type
attributes:
label: Type of Feature
description: What type of feature is this?
options:
- User Interface (UI)
- User Experience (UX)
- API / Backend
- Documentation
- Integrations / Plugins
- Security / Privacy
- Performance
- Other
default: 0
validations:
required: true
- type: textarea
id: problem-statement
attributes:
label: Problem or Use Case
description: What problem does this feature solve? What are you trying to accomplish?
placeholder: |
I often need to... but currently there's no way to...
This would help me/users to...
validations:
required: true
- type: textarea
id: proposed-solution
attributes:
label: Proposed Solution
description: A clear and concise description of what you want to happen
placeholder: |
It would be great if Memos could...
For example, a button/feature that...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: Have you considered any alternative solutions or workarounds?
placeholder: |
I've tried... but it doesn't work well because...
An alternative could be...
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context, mockups, screenshots, or examples about the feature request
placeholder: |
- Similar feature in other apps: ...
- Mockups or screenshots: ...
- Related discussions: ...
+91
View File
@@ -0,0 +1,91 @@
name: Backend Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "go.mod"
- "go.sum"
- "**.go"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
GO_VERSION: "1.25.7"
jobs:
static-checks:
name: Static Checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
cache-dependency-path: go.sum
- name: Verify go.mod is tidy
run: |
go mod tidy -go=${{ env.GO_VERSION }}
git diff --exit-code
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.4.0
args: --timeout=3m
tests:
name: Tests (${{ matrix.test-group }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test-group: [store, server, plugin, other]
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
cache-dependency-path: go.sum
- name: Run tests
run: |
case "${{ matrix.test-group }}" in
store)
# Run store tests for all drivers (sqlite, mysql, postgres)
go test -v -coverprofile=coverage.out -covermode=atomic ./store/...
;;
server)
go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/...
;;
plugin)
go test -v -race -coverprofile=coverage.out -covermode=atomic ./plugin/...
;;
other)
go test -v -race -coverprofile=coverage.out -covermode=atomic \
./cmd/... ./internal/... ./proto/...
;;
esac
env:
DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }}
- name: Upload coverage
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: codecov/codecov-action@v5
with:
files: ./coverage.out
flags: ${{ matrix.test-group }}
fail_ci_if_error: false
@@ -1,44 +0,0 @@
name: build-and-push-release-image
on:
push:
branches:
# Run on pushing branches like `release/1.0.0`
- "release/*.*.*"
jobs:
build-and-push-release-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Extract build args
# Extract version from branch name
# Example: branch name `release/1.0.0` sets up env.VERSION=1.0.0
run: |
echo "VERSION=${GITHUB_REF_NAME#release/}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: neosmemo
password: ${{ secrets.DOCKER_NEOSMEMO_TOKEN }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
install: true
- name: Build and Push
id: docker_build
uses: docker/build-push-action@v3
with:
context: ./
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: neosmemo/memos:latest, neosmemo/memos:${{ env.VERSION }}
+231
View File
@@ -0,0 +1,231 @@
name: Build Binaries
# Build multi-platform binaries on release or manual trigger
# Produces distributable packages for Linux, macOS, and Windows
on:
release:
types: [published]
workflow_dispatch:
# Environment variables for build configuration
env:
GO_VERSION: "1.25.7"
NODE_VERSION: "22"
PNPM_VERSION: "10"
ARTIFACT_RETENTION_DAYS: 60
# Artifact naming: {ARTIFACT_PREFIX}_{version}_{os}_{arch}.tar.gz|zip
ARTIFACT_PREFIX: memos
jobs:
# Job 1: Extract version information
# - For git tags: use tag version (e.g., v0.28.1 -> 0.28.1)
# - For branches: use branch-name-shortSHA format
prepare:
name: Extract Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Full history for git describe
- name: Extract version
id: version
run: |
# Try to get version from git tag
TAG=$(git describe --tags --exact-match 2>/dev/null || echo "")
if [ -n "$TAG" ]; then
echo "version=${TAG#v}" >> $GITHUB_OUTPUT
echo "Version from tag: ${TAG#v}"
else
# Use branch name + short SHA
BRANCH="${GITHUB_REF_NAME//\//-}"
SHORT_SHA="${GITHUB_SHA:0:7}"
echo "version=${BRANCH}-${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "Version from branch: ${BRANCH}-${SHORT_SHA}"
fi
# Job 2: Build frontend assets
# - Builds React frontend with Vite
# - Produces static files that will be embedded in Go binary
# - Shared across all platform builds
build-frontend:
name: Build Frontend
needs: prepare
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Build frontend
working-directory: web
run: pnpm release
- name: Upload frontend artifacts
uses: actions/upload-artifact@v6
with:
name: frontend-dist
path: server/router/frontend/dist
retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
# Job 3: Build Go binaries for multiple platforms
# - Cross-compiles using native Go toolchain
# - Embeds frontend assets built in previous job
# - Produces static binaries with no external dependencies
# - Packages as tar.gz (Unix) or zip (Windows)
build-binaries:
name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }}
needs: [prepare, build-frontend]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Linux targets
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: linux
goarch: arm
goarm: "7"
# macOS targets
- goos: darwin
goarch: amd64 # Intel Macs
- goos: darwin
goarch: arm64 # Apple Silicon
# Windows targets
- goos: windows
goarch: amd64
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Download frontend artifacts
uses: actions/download-artifact@v7
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Build binary
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
CGO_ENABLED: "0"
run: |
# Determine output binary name
OUTPUT_NAME="memos"
if [ "$GOOS" = "windows" ]; then
OUTPUT_NAME="memos.exe"
fi
mkdir -p build
# Build static binary with optimizations
go build \
-trimpath \
-ldflags="-s -w -extldflags '-static'" \
-tags netgo,osusergo \
-o "build/${OUTPUT_NAME}" \
./cmd/memos
echo "✓ Built: build/${OUTPUT_NAME}"
ls -lh build/
- name: Package binary
id: package
env:
VERSION: ${{ needs.prepare.outputs.version }}
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
run: |
cd build
# Construct package name: {prefix}_{version}_{os}_{arch}[v{arm_version}]
PACKAGE_NAME="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}"
if [ -n "$GOARM" ]; then
PACKAGE_NAME="${PACKAGE_NAME}v${GOARM}"
fi
# Package based on platform
if [ "$GOOS" = "windows" ]; then
ARTIFACT_NAME="${PACKAGE_NAME}.zip"
zip -q "${ARTIFACT_NAME}" memos.exe
else
ARTIFACT_NAME="${PACKAGE_NAME}.tar.gz"
tar czf "${ARTIFACT_NAME}" memos
fi
# Output for next step
echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
echo "✓ Package created: ${ARTIFACT_NAME} ($(du -h "${ARTIFACT_NAME}" | cut -f1))"
- name: Upload binary artifact
uses: actions/upload-artifact@v6
with:
name: ${{ env.ARTIFACT_NAME }}
path: build/${{ env.ARTIFACT_NAME }}
retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
# Job 4: Upload artifacts to GitHub Release
# - Only runs when triggered by a release publish event
# - Downloads all built artifacts and attaches them to the release
release:
name: Upload Release Assets
needs: build-binaries
if: github.event_name == 'release'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
pattern: ${{ env.ARTIFACT_PREFIX }}_*
merge-multiple: true
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: artifacts/*
+166
View File
@@ -0,0 +1,166 @@
name: Build Canary Image
on:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.repository }}
cancel-in-progress: true
jobs:
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4.2.0
with:
version: 10
- uses: actions/setup-node@v6
with:
node-version: "22"
cache: pnpm
cache-dependency-path: "web/pnpm-lock.yaml"
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- run: pnpm install --frozen-lockfile
working-directory: web
- name: Run frontend build
run: pnpm release
working-directory: web
- name: Upload frontend artifacts
uses: actions/upload-artifact@v6
with:
name: frontend-dist
path: server/router/frontend/dist
retention-days: 1
build-push:
needs: build-frontend
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
steps:
- uses: actions/checkout@v6
- name: Download frontend artifacts
uses: actions/download-artifact@v7
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v6
with:
name: digests-${{ strategy.job-index }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
needs: build-push
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v7
with:
pattern: digests-*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
flavor: |
latest=false
tags: |
type=raw,value=canary
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
- name: Inspect images
run: |
docker buildx imagetools inspect neosmemo/memos:canary
docker buildx imagetools inspect ghcr.io/usememos/memos:canary
+184
View File
@@ -0,0 +1,184 @@
name: Build Stable Image
on:
push:
branches:
- "release/**"
tags:
- "v*.*.*"
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Extract version
id: version
run: |
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF_NAME#release/}" >> $GITHUB_OUTPUT
fi
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4.2.0
with:
version: 10
- uses: actions/setup-node@v6
with:
node-version: "22"
cache: pnpm
cache-dependency-path: "web/pnpm-lock.yaml"
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- run: pnpm install --frozen-lockfile
working-directory: web
- name: Run frontend build
run: pnpm release
working-directory: web
- name: Upload frontend artifacts
uses: actions/upload-artifact@v6
with:
name: frontend-dist
path: server/router/frontend/dist
retention-days: 1
build-push:
needs: [prepare, build-frontend]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
- uses: actions/checkout@v6
- name: Download frontend artifacts
uses: actions/download-artifact@v7
with:
name: frontend-dist
path: server/router/frontend/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./scripts/Dockerfile
platforms: ${{ matrix.platform }}
cache-from: type=gha,scope=build-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v6
with:
name: digests-${{ strategy.job-index }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
needs: [prepare, build-push]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Download digests
uses: actions/download-artifact@v7
with:
pattern: digests-*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
neosmemo/memos
ghcr.io/usememos/memos
tags: |
type=semver,pattern={{version}},value=${{ needs.prepare.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.prepare.outputs.version }}
type=raw,value=stable
flavor: |
latest=false
labels: |
org.opencontainers.image.version=${{ needs.prepare.outputs.version }}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf 'neosmemo/memos@sha256:%s ' *)
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
- name: Inspect images
run: |
docker buildx imagetools inspect neosmemo/memos:stable
docker buildx imagetools inspect ghcr.io/usememos/memos:stable
-70
View File
@@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
schedule:
- cron: "27 12 * * 0"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["go", "javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+17
View File
@@ -0,0 +1,17 @@
name: Demo Deploy
on:
workflow_dispatch:
jobs:
deploy-demo:
runs-on: ubuntu-latest
steps:
- name: Trigger Render Deploy
run: |
curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \
-H "Content-Type: application/json" \
-d '{"trigger": "github_action"}'
- name: Deployment Status
run: echo "Demo deployment triggered successfully on Render"
+72
View File
@@ -0,0 +1,72 @@
name: Frontend Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "web/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "22"
PNPM_VERSION: "10"
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Run lint
working-directory: web
run: pnpm lint
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- name: Install dependencies
working-directory: web
run: pnpm install --frozen-lockfile
- name: Build frontend
working-directory: web
run: pnpm build
+40
View File
@@ -0,0 +1,40 @@
name: Proto Linter
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "proto/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint Protos
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup buf
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ github.token }}
- name: Run buf lint
uses: bufbuild/buf-lint-action@v1
with:
input: proto
- name: Check buf format
run: |
if [[ $(buf format -d) ]]; then
echo "❌ Proto files are not formatted. Run 'buf format -w' to fix."
exit 1
fi
+18
View File
@@ -0,0 +1,18 @@
name: Stale Issues
on:
schedule:
- cron: "0 */8 * * *" # Every 8 hours
jobs:
close-stale:
name: Close Stale Issues
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Close stale issues
uses: actions/stale@v10.1.1
with:
days-before-issue-stale: 14
days-before-issue-close: 7
-73
View File
@@ -1,73 +0,0 @@
name: Test
on:
push:
branches:
- main
- "release/v*.*.*"
pull_request:
branches: [main]
jobs:
go-static-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
cache: true
- name: Verify go.mod is tidy
run: |
go mod tidy
git diff --exit-code
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
args: -v
skip-cache: true
eslint-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
cache: yarn
cache-dependency-path: "web/yarn.lock"
- run: yarn
working-directory: web
- name: Run eslint check
run: yarn lint
working-directory: web
frontend-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "16"
cache: yarn
cache-dependency-path: "web/yarn.lock"
- run: yarn
working-directory: web
- name: Run frontend build
run: yarn build
working-directory: web
go-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
cache: true
- name: Run all tests
run: go test -v ./... | tee test.log; exit ${PIPESTATUS[0]}
- name: Pretty print tests running time
run: grep --color=never -e '--- PASS:' -e '--- FAIL:' test.log | sed 's/[:()]//g' | awk '{print $2,$3,$4}' | sort -t' ' -nk3 -r | awk '{sum += $3; print $1,$2,$3,sum"s"}'
+22 -6
View File
@@ -1,13 +1,29 @@
# Air (hot reload) generated
.air
# temp folder
tmp
# Frontend asset
web/dist
# build folder
build
# Build artifacts
build/
bin/
memos
.DS_Store
# Plan/design documents
docs/plans/
.DS_Store
# Jetbrains
.idea
# Docker Compose Environment File
.env
dist
# VSCode settings
.vscode
# Git worktrees
.worktrees/
+89 -52
View File
@@ -1,6 +1,7 @@
version: "2"
linters:
enable:
- goimports
- revive
- govet
- staticcheck
@@ -10,55 +11,91 @@ linters:
- rowserrcheck
- nilerr
- godot
- forbidigo
- mirror
- bodyclose
disable:
- errcheck
settings:
exhaustive:
explicit-exhaustive-switch: false
staticcheck:
checks:
- all
- -ST1000
- -ST1003
- -ST1021
- -QF1003
revive:
# Default to run all linters so that new rules in the future could automatically be added to the static check.
enable-all-rules: true
rules:
# The following rules are too strict and make coding harder. We do not enable them for now.
- name: file-header
disabled: true
- name: line-length-limit
disabled: true
- name: function-length
disabled: true
- name: max-public-structs
disabled: true
- name: function-result-limit
disabled: true
- name: banned-characters
disabled: true
- name: argument-limit
disabled: true
- name: cognitive-complexity
disabled: true
- name: cyclomatic
disabled: true
- name: confusing-results
disabled: true
- name: add-constant
disabled: true
- name: flag-parameter
disabled: true
- name: nested-structs
disabled: true
- name: import-shadowing
disabled: true
- name: early-return
disabled: true
- name: use-any
disabled: true
- name: exported
disabled: true
- name: unhandled-error
disabled: true
- name: if-return
disabled: true
- name: max-control-nesting
disabled: true
- name: redefines-builtin-id
disabled: true
- name: package-comments
disabled: true
gocritic:
disabled-checks:
- ifElseChain
govet:
settings:
printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers
funcs: # Run `go tool vet help printf` to see the full configuration of `printf`.
- common.Errorf
enable-all: true
disable:
- fieldalignment
- shadow
forbidigo:
forbid:
- pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
- pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?'
issues:
exclude:
- Rollback
- fmt.Printf
- fmt.Print
linters-settings:
revive:
enable-all-rules: true
rules:
- name: file-header
disabled: true
- name: line-length-limit
disabled: true
- name: function-length
disabled: true
- name: max-public-structs
disabled: true
- name: function-result-limit
disabled: true
- name: banned-characters
disabled: true
- name: argument-limit
disabled: true
- name: cognitive-complexity
disabled: true
- name: cyclomatic
disabled: true
- name: confusing-results
disabled: true
- name: add-constant
disabled: true
- name: flag-parameter
disabled: true
- name: nested-structs
disabled: true
- name: import-shadowing
disabled: true
- name: early-return
disabled: true
gocritic:
disabled-checks:
- ifElseChain
govet:
settings:
printf:
funcs:
- common.Errorf
forbidigo:
forbid:
- 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?'
formatters:
enable:
- goimports
settings:
goimports:
local-prefixes:
- github.com/usememos/memos
-4
View File
@@ -1,4 +0,0 @@
{
"go.lintOnSave": "workspace",
"go.lintTool": "golangci-lint"
}
+572
View File
@@ -0,0 +1,572 @@
# Memos Codebase Guide for AI Agents
This document provides comprehensive guidance for AI agents working with the Memos codebase. It covers architecture, workflows, conventions, and key patterns.
## Project Overview
Memos is a self-hosted knowledge management platform built with:
- **Backend:** Go 1.25 with gRPC + Connect RPC
- **Frontend:** React 18.3 + TypeScript + Vite 7
- **Databases:** SQLite (default), MySQL, PostgreSQL
- **Protocol:** Protocol Buffers (v2) with buf for code generation
- **API Layer:** Dual protocol - Connect RPC (browsers) + gRPC-Gateway (REST)
## Architecture
### Backend Architecture
```
cmd/memos/ # Entry point
└── main.go # Cobra CLI, profile setup, server initialization
server/
├── server.go # Echo HTTP server, healthz, background runners
├── auth/ # Authentication (JWT, PAT, session)
├── router/
│ ├── api/v1/ # gRPC service implementations
│ │ ├── v1.go # Service registration, gateway & Connect setup
│ │ ├── acl_config.go # Public endpoints whitelist
│ │ ├── connect_services.go # Connect RPC handlers
│ │ ├── connect_interceptors.go # Auth, logging, recovery
│ │ └── *_service.go # Individual services (memo, user, etc.)
│ ├── frontend/ # Static file serving (SPA)
│ ├── fileserver/ # Native HTTP file serving for media
│ └── rss/ # RSS feed generation
└── runner/
├── memopayload/ # Memo payload processing (tags, links, tasks)
└── s3presign/ # S3 presigned URL management
store/ # Data layer with caching
├── driver.go # Driver interface (database operations)
├── store.go # Store wrapper with cache layer
├── cache.go # In-memory caching (instance settings, users)
├── migrator.go # Database migrations
├── db/
│ ├── db.go # Driver factory
│ ├── sqlite/ # SQLite implementation
│ ├── mysql/ # MySQL implementation
│ └── postgres/ # PostgreSQL implementation
└── migration/ # SQL migration files (embedded)
proto/ # Protocol Buffer definitions
├── api/v1/ # API v1 service definitions
└── gen/ # Generated Go & TypeScript code
```
### Frontend Architecture
```
web/
├── src/
│ ├── components/ # React components
│ ├── contexts/ # React Context (client state)
│ │ ├── AuthContext.tsx # Current user, auth state
│ │ ├── ViewContext.tsx # Layout, sort order
│ │ └── MemoFilterContext.tsx # Filters, shortcuts
│ ├── hooks/ # React Query hooks (server state)
│ │ ├── useMemoQueries.ts # Memo CRUD, pagination
│ │ ├── useUserQueries.ts # User operations
│ │ ├── useAttachmentQueries.ts # Attachment operations
│ │ └── ...
│ ├── lib/ # Utilities
│ │ ├── query-client.ts # React Query v5 client
│ │ └── connect.ts # Connect RPC client setup
│ ├── pages/ # Page components
│ └── types/proto/ # Generated TypeScript from .proto
├── package.json # Dependencies
└── vite.config.mts # Vite config with dev proxy
plugin/ # Backend plugins
├── scheduler/ # Cron jobs
├── email/ # Email delivery
├── filter/ # CEL filter expressions
├── webhook/ # Webhook dispatch
├── markdown/ # Markdown parsing & rendering
├── httpgetter/ # HTTP fetching (metadata, images)
└── storage/s3/ # S3 storage backend
```
## Key Architectural Patterns
### 1. API Layer: Dual Protocol
**Connect RPC (Browser Clients):**
- Protocol: `connectrpc.com/connect`
- Base path: `/memos.api.v1.*`
- Interceptor chain: Metadata → Logging → Recovery → Auth
- Returns type-safe responses to React frontend
- See: `server/router/api/v1/connect_interceptors.go:177-227`
**gRPC-Gateway (REST API):**
- Protocol: Standard HTTP/JSON
- Base path: `/api/v1/*`
- Uses same service implementations as Connect
- Useful for external tools, CLI clients
- See: `server/router/api/v1/v1.go:52-96`
**Authentication:**
- JWT Access Tokens (V2): Stateless, 15-min expiration, verified via `AuthenticateByAccessTokenV2`
- Personal Access Tokens (PAT): Stateful, long-lived, validated against database
- Both use `Authorization: Bearer <token>` header
- See: `server/auth/authenticator.go:17-166`
### 2. Store Layer: Interface Pattern
All database operations go through the `Driver` interface:
```go
type Driver interface {
GetDB() *sql.DB
Close() error
IsInitialized(ctx context.Context) (bool, error)
CreateMemo(ctx context.Context, create *Memo) (*Memo, error)
ListMemos(ctx context.Context, find *FindMemo) ([]*Memo, error)
UpdateMemo(ctx context.Context, update *UpdateMemo) error
DeleteMemo(ctx context.Context, delete *DeleteMemo) error
// ... similar methods for all resources
}
```
**Three Implementations:**
- `store/db/sqlite/` - SQLite (modernc.org/sqlite)
- `store/db/mysql/` - MySQL (go-sql-driver/mysql)
- `store/db/postgres/` - PostgreSQL (lib/pq)
**Caching Strategy:**
- Store wrapper maintains in-memory caches for:
- Instance settings (`instanceSettingCache`)
- Users (`userCache`)
- User settings (`userSettingCache`)
- Config: Default TTL 10 min, cleanup interval 5 min, max 1000 items
- See: `store/store.go:10-57`
### 3. Frontend State Management
**React Query v5 (Server State):**
- All API calls go through custom hooks in `web/src/hooks/`
- Query keys organized by resource: `memoKeys`, `userKeys`, `attachmentKeys`
- Default staleTime: 30s, gcTime: 5min
- Automatic refetch on window focus, reconnect
- See: `web/src/lib/query-client.ts`
**React Context (Client State):**
- `AuthContext`: Current user, auth initialization, logout
- `ViewContext`: Layout mode (LIST/MASONRY), sort order
- `MemoFilterContext`: Active filters, shortcut selection, URL sync
### 4. Database Migration System
**Migration Flow:**
1. `preMigrate`: Check if DB exists. If not, apply `LATEST.sql`
2. `checkMinimumUpgradeVersion`: Reject pre-0.22 installations
3. `applyMigrations`: Apply incremental migrations in single transaction
4. Demo mode: Seed with demo data
**Schema Versioning:**
- Stored in `system_setting` table
- Format: `major.minor.patch`
- Migration files: `store/migration/{driver}/{version}/NN__description.sql`
- See: `store/migrator.go:21-414`
### 5. Protocol Buffer Code Generation
**Definition Location:** `proto/api/v1/*.proto`
**Regeneration:**
```bash
cd proto && buf generate
```
**Generated Outputs:**
- Go: `proto/gen/api/v1/` (used by backend services)
- TypeScript: `web/src/types/proto/api/v1/` (used by frontend)
**Linting:** `proto/buf.yaml` - BASIC lint rules, FILE breaking changes
## Development Commands
### Backend
```bash
# Start dev server
go run ./cmd/memos --port 8081
# Run all tests
go test ./...
# Run tests for specific package
go test ./store/...
go test ./server/router/api/v1/test/...
# Lint (golangci-lint)
golangci-lint run
# Format imports
goimports -w .
# Run with MySQL/Postgres
DRIVER=mysql go run ./cmd/memos
DRIVER=postgres go run ./cmd/memos
```
### Frontend
```bash
# Install dependencies
cd web && pnpm install
# Start dev server (proxies API to localhost:8081)
pnpm dev
# Type checking
pnpm lint
# Auto-fix lint issues
pnpm lint:fix
# Format code
pnpm format
# Build for production
pnpm build
# Build and copy to backend
pnpm release
```
### Protocol Buffers
```bash
# Regenerate Go and TypeScript from .proto files
cd proto && buf generate
# Lint proto files
cd proto && buf lint
# Check for breaking changes
cd proto && buf breaking --against .git#main
```
## Key Workflows
### Adding a New API Endpoint
1. **Define in Protocol Buffer:**
- Edit `proto/api/v1/*_service.proto`
- Add request/response messages
- Add RPC method to service
2. **Regenerate Code:**
```bash
cd proto && buf generate
```
3. **Implement Service (Backend):**
- Add method to `server/router/api/v1/*_service.go`
- Follow existing patterns: fetch user, validate, call store
- Add Connect wrapper to `server/router/api/v1/connect_services.go` (optional, same implementation)
4. **If Public Endpoint:**
- Add to `server/router/api/v1/acl_config.go:11-34`
5. **Create Frontend Hook (if needed):**
- Add query/mutation to `web/src/hooks/use*Queries.ts`
- Use existing query key factories
### Database Schema Changes
1. **Create Migration Files:**
```
store/migration/sqlite/0.28/1__add_new_column.sql
store/migration/mysql/0.28/1__add_new_column.sql
store/migration/postgres/0.28/1__add_new_column.sql
```
2. **Update LATEST.sql:**
- Add change to `store/migration/{driver}/LATEST.sql`
3. **Update Store Interface (if new table/model):**
- Add methods to `store/driver.go:8-71`
- Implement in `store/db/{driver}/*.go`
4. **Test Migration:**
- Run `go test ./store/test/...` to verify
### Adding a New Frontend Page
1. **Create Page Component:**
- Add to `web/src/pages/NewPage.tsx`
- Use existing hooks for data fetching
2. **Add Route:**
- Edit `web/src/App.tsx` (or router configuration)
3. **Use React Query:**
```typescript
import { useMemos } from "@/hooks/useMemoQueries";
const { data, isLoading } = useMemos({ filter: "..." });
```
4. **Use Context for Client State:**
```typescript
import { useView } from "@/contexts/ViewContext";
const { layout, toggleSortOrder } = useView();
```
## Testing
### Backend Tests
**Test Pattern:**
```go
func TestMemoCreation(t *testing.T) {
ctx := context.Background()
store := test.NewTestingStore(ctx, t)
// Create test user
user, _ := createTestUser(ctx, store, t)
// Execute operation
memo, err := store.CreateMemo(ctx, &store.Memo{
CreatorID: user.ID,
Content: "Test memo",
// ...
})
require.NoError(t, err)
assert.NotNil(t, memo)
}
```
**Test Utilities:**
- `store/test/store.go:22-35` - `NewTestingStore()` creates isolated DB
- `store/test/store.go:37-77` - `resetTestingDB()` cleans tables
- Test DB determined by `DRIVER` env var (default: sqlite)
**Running Tests:**
```bash
# All tests
go test ./...
# Specific package
go test ./store/...
go test ./server/router/api/v1/test/...
# With coverage
go test -cover ./...
```
### Frontend Testing
**TypeScript Checking:**
```bash
cd web && pnpm lint
```
**No Automated Tests:**
- Frontend relies on TypeScript checking and manual validation
- React Query DevTools available in dev mode (bottom-left)
## Code Conventions
### Go
**Error Handling:**
- Use `github.com/pkg/errors` for wrapping: `errors.Wrap(err, "context")`
- Return structured gRPC errors: `status.Errorf(codes.NotFound, "message")`
**Naming:**
- Package names: lowercase, single word (e.g., `store`, `server`)
- Interfaces: `Driver`, `Store`, `Service`
- Methods: PascalCase for exported, camelCase for internal
**Comments:**
- Public exported functions must have comments (godot enforces)
- Use `//` for single-line, `/* */` for multi-line
**Imports:**
- Grouped: stdlib, third-party, local
- Sorted alphabetically within groups
- Use `goimports -w .` to format
### TypeScript/React
**Components:**
- Functional components with hooks
- Use `useMemo`, `useCallback` for optimization
- Props interfaces: `interface Props { ... }`
**State Management:**
- Server state: React Query hooks
- Client state: React Context
- Avoid direct useState for server data
**Styling:**
- Tailwind CSS v4 via `@tailwindcss/vite`
- Use `clsx` and `tailwind-merge` for conditional classes
**Imports:**
- Absolute imports with `@/` alias
- Group: React, third-party, local
- Auto-organized by Biome
## Important Files Reference
### Backend Entry Points
| File | Purpose |
|------|---------|
| `cmd/memos/main.go` | Server entry point, CLI setup |
| `server/server.go` | Echo server initialization, background runners |
| `store/store.go` | Store wrapper with caching |
| `store/driver.go` | Database driver interface |
### API Layer
| File | Purpose |
|------|---------|
| `server/router/api/v1/v1.go` | Service registration, gateway setup |
| `server/router/api/v1/acl_config.go` | Public endpoints whitelist |
| `server/router/api/v1/connect_interceptors.go` | Connect interceptors |
| `server/auth/authenticator.go` | Authentication logic |
### Frontend Core
| File | Purpose |
|------|---------|
| `web/src/lib/query-client.ts` | React Query client configuration |
| `web/src/contexts/AuthContext.tsx` | User authentication state |
| `web/src/contexts/ViewContext.tsx` | UI preferences |
| `web/src/contexts/MemoFilterContext.tsx` | Filter state |
| `web/src/hooks/useMemoQueries.ts` | Memo queries/mutations |
### Data Layer
| File | Purpose |
|------|---------|
| `store/memo.go` | Memo model definitions, store methods |
| `store/user.go` | User model definitions |
| `store/attachment.go` | Attachment model definitions |
| `store/migrator.go` | Migration logic |
| `store/db/db.go` | Driver factory |
| `store/db/sqlite/sqlite.go` | SQLite driver implementation |
## Configuration
### Backend Environment Variables
| Variable | Default | Description |
|----------|----------|-------------|
| `MEMOS_DEMO` | `false` | Enable demo mode |
| `MEMOS_PORT` | `8081` | HTTP port |
| `MEMOS_ADDR` | `` | Bind address (empty = all) |
| `MEMOS_DATA` | `~/.memos` | Data directory |
| `MEMOS_DRIVER` | `sqlite` | Database: `sqlite`, `mysql`, `postgres` |
| `MEMOS_DSN` | `` | Database connection string |
| `MEMOS_INSTANCE_URL` | `` | Instance base URL |
### Frontend Environment Variables
| Variable | Default | Description |
|----------|----------|-------------|
| `DEV_PROXY_SERVER` | `http://localhost:8081` | Backend proxy target |
## CI/CD
### GitHub Workflows
**Backend Tests** (`.github/workflows/backend-tests.yml`):
- Runs on `go.mod`, `go.sum`, `**.go` changes
- Steps: verify `go mod tidy`, golangci-lint, all tests
**Frontend Tests** (`.github/workflows/frontend-tests.yml`):
- Runs on `web/**` changes
- Steps: pnpm install, lint, build
**Proto Lint** (`.github/workflows/proto-linter.yml`):
- Runs on `.proto` changes
- Steps: buf lint, buf breaking check
### Linting Configuration
**Go** (`.golangci.yaml`):
- Linters: revive, govet, staticcheck, misspell, gocritic, etc.
- Formatter: goimports
- Forbidden: `fmt.Errorf`, `ioutil.ReadDir`
**TypeScript** (`web/biome.json`):
- Linting: Biome (ESLint replacement)
- Formatting: Biome (Prettier replacement)
- Line width: 140 characters
- Semicolons: always
## Common Tasks
### Debugging API Issues
1. Check Connect interceptor logs: `server/router/api/v1/connect_interceptors.go:79-105`
2. Verify endpoint is in `acl_config.go` if public
3. Check authentication via `auth/authenticator.go:133-165`
4. Test with curl: `curl -H "Authorization: Bearer <token>" http://localhost:8081/api/v1/...`
### Debugging Frontend State
1. Open React Query DevTools (bottom-left in dev)
2. Inspect query cache, mutations, refetch behavior
3. Check Context state via React DevTools
4. Verify filter state in MemoFilterContext
### Running Tests Against Multiple Databases
```bash
# SQLite (default)
DRIVER=sqlite go test ./...
# MySQL (requires running MySQL server)
DRIVER=mysql DSN="user:pass@tcp(localhost:3306)/memos" go test ./...
# PostgreSQL (requires running PostgreSQL server)
DRIVER=postgres DSN="postgres://user:pass@localhost:5432/memos" go test ./...
```
## Plugin System
Backend supports pluggable components in `plugin/`:
| Plugin | Purpose |
|--------|----------|
| `scheduler` | Cron-based job scheduling |
| `email` | SMTP email delivery |
| `filter` | CEL expression filtering |
| `webhook` | HTTP webhook dispatch |
| `markdown` | Markdown parsing (goldmark) |
| `httpgetter` | HTTP content fetching |
| `storage/s3` | S3-compatible storage |
Each plugin has its own README with usage examples.
## Performance Considerations
### Backend
- Database queries use pagination (`limit`, `offset`)
- In-memory caching reduces DB hits for frequently accessed data
- WAL journal mode for SQLite (reduces locking)
- Thumbnail generation limited to 3 concurrent operations
### Frontend
- React Query reduces redundant API calls
- Infinite queries for large lists (pagination)
- Manual chunks: `utils-vendor`, `mermaid-vendor`, `leaflet-vendor`
- Lazy loading for heavy components
## Security Notes
- JWT secrets must be kept secret (generated on first run in production mode)
- Personal Access Tokens stored as SHA-256 hashes in database
- CSRF protection via SameSite cookies
- CORS enabled for all origins (configure for production)
- Input validation at service layer
- SQL injection prevention via parameterized queries
+1 -1
View File
@@ -1,2 +1,2 @@
# These owners will be the default owners for everything in the repo.
* @boojack @lqwakeup
* @boojack @johnnyjoygh
-31
View File
@@ -1,31 +0,0 @@
# Build frontend dist.
FROM node:16.15.0-alpine AS frontend
WORKDIR /frontend-build
COPY ./web/ .
RUN yarn
RUN yarn build
# Build backend exec file.
FROM golang:1.18.3-alpine3.16 AS backend
WORKDIR /backend-build
RUN apk update
RUN apk --no-cache add gcc musl-dev
COPY . .
COPY --from=frontend /frontend-build/dist ./server/dist
RUN go build -o memos ./bin/server/main.go
# Make workspace with above generated files.
FROM alpine:3.16.0 AS monolithic
WORKDIR /usr/local/memos
COPY --from=backend /backend-build/memos /usr/local/memos/
# Directory to store the data, which can be referenced as the mounting point.
RUN mkdir -p /var/opt/memos
ENTRYPOINT ["./memos", "--mode", "prod", "--port", "5230"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Memos
Copyright (c) 2025 Memos
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+90 -28
View File
@@ -1,49 +1,111 @@
<p align="center"><a href="https://usememos.com"><img height="64px" src="https://raw.githubusercontent.com/usememos/memos/main/resources/logo-full.webp" alt="✍️ memos" /></a></p>
# Memos
<p align="center">An open source, self-hosted knowledge base that works with a SQLite db file.</p>
<img align="right" height="96px" src="https://raw.githubusercontent.com/usememos/.github/refs/heads/main/assets/logo-rounded.png" alt="Memos" />
<p align="center">
<a href="https://github.com/usememos/memos/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/usememos/memos" /></a>
<a href="https://hub.docker.com/r/neosmemo/memos"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/neosmemo/memos.svg" /></a>
<img alt="Go report" src="https://goreportcard.com/badge/github.com/usememos/memos" />
</p>
An open-source, self-hosted note-taking service. Your thoughts, your data, your control — no tracking, no ads, no subscription fees.
<p align="center">
<a href="https://demo.usememos.com/">Live Demo</a> •
<a href="https://t.me/+-_tNF1k70UU4ZTc9">Discuss in Telegram 👾</a>
</p>
[![Home](https://img.shields.io/badge/🏠-usememos.com-blue?style=flat-square)](https://usememos.com)
[![Live Demo](https://img.shields.io/badge/✨-Try%20Demo-orange?style=flat-square)](https://demo.usememos.com/)
[![Docs](https://img.shields.io/badge/📚-Documentation-green?style=flat-square)](https://usememos.com/docs)
[![Discord](https://img.shields.io/badge/💬-Discord-5865f2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/tfPJa4UmAv)
[![Docker Pulls](https://img.shields.io/docker/pulls/neosmemo/memos?style=flat-square&logo=docker)](https://hub.docker.com/r/neosmemo/memos)
![demo](https://raw.githubusercontent.com/usememos/memos/main/resources/demo.webp)
<img src="https://raw.githubusercontent.com/usememos/.github/refs/heads/main/assets/demo.png" alt="Memos Demo Screenshot" height="512" />
### 💎 Featured Sponsors
[**Warp** — The AI-powered terminal built for speed and collaboration](https://go.warp.dev/memos)
<a href="https://go.warp.dev/memos" target="_blank" rel="noopener">
<img src="https://raw.githubusercontent.com/warpdotdev/brand-assets/main/Github/Sponsor/Warp-Github-LG-02.png" alt="Warp - The AI-powered terminal built for speed and collaboration" width="512" />
</a>
<p></p>
[**TestMu AI** - The worlds first full-stack Agentic AI Quality Engineering platform](https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos)
<a href="https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos" target="_blank" rel="noopener">
<img src="https://usememos.com/sponsors/testmu.svg" alt="TestMu AI" height="36" />
</a>
<p></p>
[**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor)
<a href="https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor" target="_blank" rel="noopener">
<img src="https://usememos.com/sponsors/ssd-nodes.svg" alt="SSD Nodes" height="72" />
</a>
## Overview
Memos is a privacy-first, self-hosted knowledge base for personal notes, team wikis, and knowledge management. Built with Go and React, it runs as a single binary with minimal resource usage.
## Features
- 🦄 Fully open source;
- 📜 Writing in plain textarea without any burden,
- and support some useful markdown syntax 💪.
- 🌄 Share the memo in a pretty image or personal page like Twitter;
- 🚀 Fast self-hosting with `Docker`;
- 🤠 Pleasant UI and UX;
- **Privacy-First** — Self-hosted on your infrastructure with zero telemetry, no tracking, and no ads.
- **Markdown Native** — Full markdown support with plain text storage. Your data is always portable.
- **Lightweight** — Single Go binary with a React frontend. Low memory footprint, starts in seconds.
- **Easy to Deploy** — One-line Docker install. Supports SQLite, MySQL, and PostgreSQL.
- **Developer-Friendly** — Full REST and gRPC APIs for integration with existing workflows.
- **Clean Interface** — Minimal design with dark mode and mobile-responsive layout.
## Deploy with Docker
## Quick Start
### Docker Run
### Docker (Recommended)
```docker
docker run -d --name memos -p 5230:5230 -v ~/.memos/:/var/opt/memos neosmemo/memos:latest
```bash
docker run -d \
--name memos \
-p 5230:5230 \
-v ~/.memos:/var/opt/memos \
neosmemo/memos:stable
```
Memos should be running at [http://localhost:5230](http://localhost:5230). If the `~/.memos/` does not have a `memos_prod.db` file, then memos will auto generate it.
Open `http://localhost:5230` and start writing!
### Docker Compose
### Try the Live Demo
See more in the example [`docker-compose.yaml`](./docker-compose.yaml) file.
Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first!
### Other Installation Methods
- **Docker Compose** - Recommended for production deployments
- **Pre-built Binaries** - Available for Linux, macOS, and Windows
- **Kubernetes** - Helm charts and manifests available
- **Build from Source** - For development and customization
See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions.
## Contributing
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated. 🥰
Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations.
Gets more about [development guide](https://github.com/usememos/memos/tree/main/docs/development.md).
- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md)
- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md)
- [Submit pull requests](https://github.com/usememos/memos/pulls)
- [Improve documentation](https://github.com/usememos/memos/tree/main/docs)
- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales)
## Star history
## Sponsors
Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing!
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=usememos/memos&type=Date)](https://star-history.com/#usememos/memos&Date)
## License
Memos is open-source software licensed under the [MIT License](LICENSE).
## Privacy Policy
Memos is built with privacy as a core principle. As a self-hosted application, all your data stays on your infrastructure. There is no telemetry, no tracking, and no data collection. See our [Privacy Policy](https://usememos.com/privacy) for details.
---
**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)**
<a href="https://vercel.com/oss">
<img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge.svg" />
</a>
+46
View File
@@ -0,0 +1,46 @@
# Security Policy
## Project Status
Memos is currently in beta (v0.x). While we take security seriously, we are not yet ready for formal CVE assignments or coordinated disclosure programs.
## Reporting Security Issues
### For All Security Concerns:
Please report via **email only**: dev@usememos.com
**DO NOT open public GitHub issues for security vulnerabilities.**
Include in your report:
- Description of the issue
- Steps to reproduce
- Affected versions
- Your assessment of severity
### What to Expect:
- We will acknowledge your report as soon as we can
- Fixes will be included in regular releases without special security advisories
- No CVEs will be assigned during the beta phase
- Credit will be given in release notes if you wish
### For Non-Security Bugs:
Use GitHub issues for functionality bugs, feature requests, and general questions.
## Philosophy
As a beta project, we prioritize:
1. **Rapid iteration** over lengthy disclosure timelines
2. **Quick patches** over formal security processes
3. **Transparency** about our beta status
We plan to implement formal vulnerability disclosure and CVE handling after reaching v1.0 stable.
## Self-Hosting Security
Since Memos is self-hosted software:
- Keep your instance updated to the latest release
- Don't expose your instance directly to the internet without authentication
- Use reverse proxies (nginx, Caddy) with rate limiting
- Review the deployment documentation for security best practices
Thank you for helping improve Memos!
-21
View File
@@ -1,21 +0,0 @@
package api
// RowStatus is the status for a row.
type RowStatus string
const (
// Normal is the status for a normal row.
Normal RowStatus = "NORMAL"
// Archived is the status for an archived row.
Archived RowStatus = "ARCHIVED"
)
func (e RowStatus) String() string {
switch e {
case Normal:
return "NORMAL"
case Archived:
return "ARCHIVED"
}
return ""
}
-13
View File
@@ -1,13 +0,0 @@
package api
type Signin struct {
Email string `json:"email"`
Password string `json:"password"`
}
type Signup struct {
Email string `json:"email"`
Role Role `json:"role"`
Name string `json:"name"`
Password string `json:"password"`
}
-22
View File
@@ -1,22 +0,0 @@
package api
// CacheNamespace is the type of a cache.
type CacheNamespace string
const (
// UserCache is the cache type of users.
UserCache CacheNamespace = "u"
// MemoCache is the cache type of memos.
MemoCache CacheNamespace = "m"
// ShortcutCache is the cache type of shortcuts.
ShortcutCache CacheNamespace = "s"
// ResourceCache is the cache type of resources.
ResourceCache CacheNamespace = "r"
)
// CacheService is the service for caches.
type CacheService interface {
FindCache(namespace CacheNamespace, id int, entry interface{}) (bool, error)
UpsertCache(namespace CacheNamespace, id int, entry interface{}) error
DeleteCache(namespace CacheNamespace, id int)
}
-85
View File
@@ -1,85 +0,0 @@
package api
// Visibility is the type of a visibility.
type Visibility string
const (
// Public is the PUBLIC visibility.
Public Visibility = "PUBLIC"
// Protected is the PROTECTED visibility.
Protected Visibility = "PROTECTED"
// Privite is the PRIVATE visibility.
Privite Visibility = "PRIVATE"
)
func (e Visibility) String() string {
switch e {
case Public:
return "PUBLIC"
case Protected:
return "PROTECTED"
case Privite:
return "PRIVATE"
}
return "PRIVATE"
}
type Memo struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Content string `json:"content"`
Visibility Visibility `json:"visibility"`
Pinned bool `json:"pinned"`
// Related fields
Creator *User `json:"creator"`
}
type MemoCreate struct {
// Standard fields
CreatorID int
// Domain specific fields
Visibility Visibility `json:"visibility"`
Content string `json:"content"`
}
type MemoPatch struct {
ID int
// Standard fields
CreatedTs *int64 `json:"createdTs"`
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Content *string `json:"content"`
Visibility *Visibility `json:"visibility"`
}
type MemoFind struct {
ID *int `json:"id"`
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
CreatorID *int `json:"creatorId"`
// Domain specific fields
Pinned *bool
ContentSearch *string
VisibilityList []Visibility
// Pagination
Limit int
Offset int
}
type MemoDelete struct {
ID int `json:"id"`
}
-21
View File
@@ -1,21 +0,0 @@
package api
type MemoOrganizer struct {
ID int
// Domain specific fields
MemoID int
UserID int
Pinned bool
}
type MemoOrganizerFind struct {
MemoID int
UserID int
}
type MemoOrganizerUpsert struct {
MemoID int
UserID int
Pinned bool `json:"pinned"`
}
-44
View File
@@ -1,44 +0,0 @@
package api
type Resource struct {
ID int `json:"id"`
// Standard fields
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Filename string `json:"filename"`
Blob []byte `json:"-"`
Type string `json:"type"`
Size int64 `json:"size"`
}
type ResourceCreate struct {
// Standard fields
CreatorID int
// Domain specific fields
Filename string `json:"filename"`
Blob []byte `json:"blob"`
Type string `json:"type"`
Size int64 `json:"size"`
}
type ResourceFind struct {
ID *int `json:"id"`
// Standard fields
CreatorID *int `json:"creatorId"`
// Domain specific fields
Filename *string `json:"filename"`
}
type ResourceDelete struct {
ID int
// Standard fields
CreatorID int
}
-49
View File
@@ -1,49 +0,0 @@
package api
type Shortcut struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatorID int `json:"creatorId"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Title string `json:"title"`
Payload string `json:"payload"`
}
type ShortcutCreate struct {
// Standard fields
CreatorID int
// Domain specific fields
Title string `json:"title"`
Payload string `json:"payload"`
}
type ShortcutPatch struct {
ID int
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Title *string `json:"title"`
Payload *string `json:"payload"`
}
type ShortcutFind struct {
ID *int
// Standard fields
CreatorID *int
// Domain specific fields
Title *string `json:"title"`
}
type ShortcutDelete struct {
ID int
}
-8
View File
@@ -1,8 +0,0 @@
package api
import "github.com/usememos/memos/server/profile"
type SystemStatus struct {
Host *User `json:"host"`
Profile *profile.Profile `json:"profile"`
}
-100
View File
@@ -1,100 +0,0 @@
package api
import (
"fmt"
"github.com/usememos/memos/common"
)
// Role is the type of a role.
type Role string
const (
// Host is the HOST role.
Host Role = "HOST"
// NormalUser is the USER role.
NormalUser Role = "USER"
)
func (e Role) String() string {
switch e {
case Host:
return "HOST"
case NormalUser:
return "USER"
}
return "USER"
}
type User struct {
ID int `json:"id"`
// Standard fields
RowStatus RowStatus `json:"rowStatus"`
CreatedTs int64 `json:"createdTs"`
UpdatedTs int64 `json:"updatedTs"`
// Domain specific fields
Email string `json:"email"`
Role Role `json:"role"`
Name string `json:"name"`
PasswordHash string `json:"-"`
OpenID string `json:"openId"`
UserSettingList []*UserSetting `json:"userSettingList"`
}
type UserCreate struct {
// Domain specific fields
Email string `json:"email"`
Role Role `json:"role"`
Name string `json:"name"`
Password string `json:"password"`
PasswordHash string
OpenID string
}
func (create UserCreate) Validate() error {
if !common.ValidateEmail(create.Email) {
return fmt.Errorf("invalid email format")
}
if len(create.Email) < 6 {
return fmt.Errorf("email is too short, minimum length is 6")
}
if len(create.Password) < 6 {
return fmt.Errorf("password is too short, minimum length is 6")
}
return nil
}
type UserPatch struct {
ID int
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Email *string `json:"email"`
Name *string `json:"name"`
Password *string `json:"password"`
ResetOpenID *bool `json:"resetOpenId"`
PasswordHash *string
OpenID *string
}
type UserFind struct {
ID *int `json:"id"`
// Standard fields
RowStatus *RowStatus `json:"rowStatus"`
// Domain specific fields
Email *string `json:"email"`
Role *Role
Name *string `json:"name"`
OpenID *string
}
type UserDelete struct {
ID int
}
-136
View File
@@ -1,136 +0,0 @@
package api
import (
"encoding/json"
"fmt"
)
type UserSettingKey string
const (
// UserSettingLocaleKey is the key type for user locale.
UserSettingLocaleKey UserSettingKey = "locale"
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility"
// UserSettingEditorFontStyleKey is the key type for editor font style.
UserSettingEditorFontStyleKey UserSettingKey = "editorFontStyle"
// UserSettingEditorFontStyleKey is the key type for mobile editor style.
UserSettingMobileEditorStyleKey UserSettingKey = "mobileEditorStyle"
)
// String returns the string format of UserSettingKey type.
func (key UserSettingKey) String() string {
switch key {
case UserSettingLocaleKey:
return "locale"
case UserSettingMemoVisibilityKey:
return "memoVisibility"
case UserSettingEditorFontStyleKey:
return "editorFontFamily"
case UserSettingMobileEditorStyleKey:
return "mobileEditorStyle"
}
return ""
}
var (
UserSettingLocaleValue = []string{"en", "zh", "vi"}
UserSettingMemoVisibilityValue = []Visibility{Privite, Protected, Public}
UserSettingEditorFontStyleValue = []string{"normal", "mono"}
UserSettingMobileEditorStyleValue = []string{"normal", "float"}
)
type UserSetting struct {
UserID int
Key UserSettingKey `json:"key"`
// Value is a JSON string with basic value
Value string `json:"value"`
}
type UserSettingUpsert struct {
UserID int
Key UserSettingKey `json:"key"`
Value string `json:"value"`
}
func (upsert UserSettingUpsert) Validate() error {
if upsert.Key == UserSettingLocaleKey {
localeValue := "en"
err := json.Unmarshal([]byte(upsert.Value), &localeValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting locale value")
}
invalid := true
for _, value := range UserSettingLocaleValue {
if localeValue == value {
invalid = false
break
}
}
if invalid {
return fmt.Errorf("invalid user setting locale value")
}
} else if upsert.Key == UserSettingMemoVisibilityKey {
memoVisibilityValue := Privite
err := json.Unmarshal([]byte(upsert.Value), &memoVisibilityValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting memo visibility value")
}
invalid := true
for _, value := range UserSettingMemoVisibilityValue {
if memoVisibilityValue == value {
invalid = false
break
}
}
if invalid {
return fmt.Errorf("invalid user setting memo visibility value")
}
} else if upsert.Key == UserSettingEditorFontStyleKey {
editorFontStyleValue := "normal"
err := json.Unmarshal([]byte(upsert.Value), &editorFontStyleValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting editor font style")
}
invalid := true
for _, value := range UserSettingEditorFontStyleValue {
if editorFontStyleValue == value {
invalid = false
break
}
}
if invalid {
return fmt.Errorf("invalid user setting editor font style value")
}
} else if upsert.Key == UserSettingMobileEditorStyleKey {
mobileEditorStyleValue := "normal"
err := json.Unmarshal([]byte(upsert.Value), &mobileEditorStyleValue)
if err != nil {
return fmt.Errorf("failed to unmarshal user setting mobile editor style")
}
invalid := true
for _, value := range UserSettingMobileEditorStyleValue {
if mobileEditorStyleValue == value {
invalid = false
break
}
}
if invalid {
return fmt.Errorf("invalid user setting mobile editor style value")
}
} else {
return fmt.Errorf("invalid user setting key")
}
return nil
}
type UserSettingFind struct {
UserID int
Key *UserSettingKey `json:"key"`
}
-74
View File
@@ -1,74 +0,0 @@
package main
import (
"os"
_ "github.com/mattn/go-sqlite3"
"context"
"fmt"
"github.com/usememos/memos/server"
"github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store"
DB "github.com/usememos/memos/store/db"
)
const (
greetingBanner = `
███╗ ███╗███████╗███╗ ███╗ ██████╗ ███████╗
████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔════╝
██╔████╔██║█████╗ ██╔████╔██║██║ ██║███████╗
██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║╚════██║
██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝███████║
╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
`
)
func run(profile *profile.Profile) error {
ctx := context.Background()
db := DB.NewDB(profile)
if err := db.Open(ctx); err != nil {
return fmt.Errorf("cannot open db: %w", err)
}
s := server.NewServer(profile)
storeInstance := store.New(db.Db, profile)
s.Store = storeInstance
println(greetingBanner)
fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
return s.Run()
}
func execute() error {
profile, err := profile.GetProfile()
if err != nil {
return err
}
println("---")
println("profile")
println("mode:", profile.Mode)
println("port:", profile.Port)
println("dsn:", profile.DSN)
println("version:", profile.Version)
println("---")
if err := run(profile); err != nil {
fmt.Printf("error: %+v\n", err)
return err
}
return nil
}
func main() {
if err := execute(); err != nil {
os.Exit(1)
}
}
+176
View File
@@ -0,0 +1,176 @@
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/usememos/memos/internal/profile"
"github.com/usememos/memos/internal/version"
"github.com/usememos/memos/server"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
)
var (
rootCmd = &cobra.Command{
Use: "memos",
Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`,
Run: func(_ *cobra.Command, _ []string) {
instanceProfile := &profile.Profile{
Demo: viper.GetBool("demo"),
Addr: viper.GetString("addr"),
Port: viper.GetInt("port"),
UNIXSock: viper.GetString("unix-sock"),
Data: viper.GetString("data"),
Driver: viper.GetString("driver"),
DSN: viper.GetString("dsn"),
InstanceURL: viper.GetString("instance-url"),
}
instanceProfile.Version = version.GetCurrentVersion()
if err := instanceProfile.Validate(); err != nil {
slog.Error("failed to validate profile", "error", err)
return
}
ctx, cancel := context.WithCancel(context.Background())
dbDriver, err := db.NewDBDriver(instanceProfile)
if err != nil {
cancel()
slog.Error("failed to create db driver", "error", err)
return
}
storeInstance := store.New(dbDriver, instanceProfile)
if err := storeInstance.Migrate(ctx); err != nil {
cancel()
slog.Error("failed to migrate", "error", err)
return
}
s, err := server.NewServer(ctx, instanceProfile, storeInstance)
if err != nil {
cancel()
slog.Error("failed to create server", "error", err)
return
}
c := make(chan os.Signal, 1)
// Trigger graceful shutdown on SIGINT or SIGTERM.
// The default signal sent by the `kill` command is SIGTERM,
// which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
if err := s.Start(ctx); err != nil {
if err != http.ErrServerClosed {
slog.Error("failed to start server", "error", err)
cancel()
return
}
}
printGreetings(instanceProfile)
go func() {
<-c
s.Shutdown(ctx)
cancel()
}()
// Wait for CTRL-C.
<-ctx.Done()
},
}
)
func init() {
viper.SetDefault("demo", false)
viper.SetDefault("driver", "sqlite")
viper.SetDefault("port", 8081)
rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode")
rootCmd.PersistentFlags().String("addr", "", "address of server")
rootCmd.PersistentFlags().Int("port", 8081, "port of server")
rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port")
rootCmd.PersistentFlags().String("data", "", "data directory")
rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance")
if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil {
panic(err)
}
if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil {
panic(err)
}
if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil {
panic(err)
}
if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil {
panic(err)
}
if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil {
panic(err)
}
if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil {
panic(err)
}
if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil {
panic(err)
}
if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil {
panic(err)
}
viper.SetEnvPrefix("memos")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv()
}
func printGreetings(profile *profile.Profile) {
fmt.Printf("Memos %s started successfully!\n", profile.Version)
if profile.Demo {
fmt.Fprint(os.Stderr, "Development mode is enabled\n")
if profile.DSN != "" {
fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN)
}
}
// Server information
fmt.Printf("Data directory: %s\n", profile.Data)
fmt.Printf("Database driver: %s\n", profile.Driver)
// Connection information
if len(profile.UNIXSock) == 0 {
if len(profile.Addr) == 0 {
fmt.Printf("Server running on port %d\n", profile.Port)
fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port)
} else {
fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port)
fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port)
}
} else {
fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock)
}
fmt.Println()
fmt.Printf("Documentation: %s\n", "https://usememos.com")
fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos")
fmt.Println("\nHappy note-taking!")
}
func main() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
-72
View File
@@ -1,72 +0,0 @@
package common
import (
"errors"
)
// Code is the error code.
type Code int
// Application error codes.
const (
// 0 ~ 99 general error.
Ok Code = 0
Internal Code = 1
NotAuthorized Code = 2
Invalid Code = 3
NotFound Code = 4
Conflict Code = 5
NotImplemented Code = 6
)
// Error represents an application-specific error. Application errors can be
// unwrapped by the caller to extract out the code & message.
//
// Any non-application error (such as a disk error) should be reported as an
// Internal error and the human user should only see "Internal error" as the
// message. These low-level internal error details should only be logged and
// reported to the operator of the application (not the end user).
type Error struct {
// Machine-readable error code.
Code Code
// Embedded error.
Err error
}
// Error implements the error interface. Not used by the application otherwise.
func (e *Error) Error() string {
return e.Err.Error()
}
// ErrorCode unwraps an application error and returns its code.
// Non-application errors always return EINTERNAL.
func ErrorCode(err error) Code {
var e *Error
if err == nil {
return Ok
} else if errors.As(err, &e) {
return e.Code
}
return Internal
}
// ErrorMessage unwraps an application error and returns its message.
// Non-application errors always return "Internal error".
func ErrorMessage(err error) string {
var e *Error
if err == nil {
return ""
} else if errors.As(err, &e) {
return e.Err.Error()
}
return "Internal error."
}
// Errorf is a helper function to return an Error with a given code and error.
func Errorf(code Code, err error) *Error {
return &Error{
Code: code,
Err: err,
}
}
-30
View File
@@ -1,30 +0,0 @@
package common
import (
"net/mail"
"strings"
"github.com/google/uuid"
)
// HasPrefixes returns true if the string s has any of the given prefixes.
func HasPrefixes(src string, prefixes ...string) bool {
for _, prefix := range prefixes {
if strings.HasPrefix(src, prefix) {
return true
}
}
return false
}
// ValidateEmail validates the email.
func ValidateEmail(email string) bool {
if _, err := mail.ParseAddress(email); err != nil {
return false
}
return true
}
func GenUUID() string {
return uuid.New().String()
}
-40
View File
@@ -1,40 +0,0 @@
# Development
Memos is built with a curated tech stack. It is optimized for developer experience and is very easy to start working on the code:
1. It has no external dependency.
2. It requires zero config.
3. 1 command to start backend and 1 command to start frontend, both with live reload support.
## Tech Stack
![tech-stack](https://raw.githubusercontent.com/usememos/memos/main/resources/tech-stack.png)
## Prerequisites
- [Go](https://golang.org/doc/install)
- [Air](https://github.com/cosmtrek/air#installation) for backend live reload
- [Node.js](https://nodejs.org/)
- [yarn](https://yarnpkg.com/getting-started/install)
## Steps
1. pull source code
```bash
git clone https://github.com/usememos/memos
```
2. start backend using air(with live reload)
```bash
air -c scripts/.air.toml
```
3. start frontend dev server
```bash
cd web && yarn && yarn dev
```
Memos should now be running at [http://localhost:3000](http://localhost:3000) and change either frontend or backend code would trigger live reload.
+123 -27
View File
@@ -1,38 +1,134 @@
module github.com/usememos/memos
go 1.17
require github.com/mattn/go-sqlite3 v1.14.9
require github.com/google/uuid v1.3.0
go 1.25.7
require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/net v0.0.0-20220728030405-41545e8bf201 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
connectrpc.com/connect v1.19.1
github.com/aws/aws-sdk-go-v2 v1.39.2
github.com/aws/aws-sdk-go-v2/config v1.31.12
github.com/aws/aws-sdk-go-v2/credentials v1.18.16
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.4
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3
github.com/docker/docker v28.5.1+incompatible
github.com/go-sql-driver/mysql v1.9.3
github.com/google/cel-go v0.26.1
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v5 v5.0.3
github.com/lib/pq v1.10.9
github.com/lithammer/shortuuid/v4 v4.2.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.10.1
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.40.0
github.com/testcontainers/testcontainers-go/modules/mysql v0.40.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0
github.com/yuin/goldmark v1.7.13
golang.org/x/crypto v0.47.0
golang.org/x/mod v0.31.0
golang.org/x/net v0.49.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.19.0
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1
google.golang.org/grpc v1.75.1
modernc.org/sqlite v1.38.2
)
require (
github.com/gorilla/context v1.1.1 // indirect
github.com/labstack/echo/v4 v4.9.0
github.com/labstack/gommon v0.3.1 // indirect
cel.dev/expr v0.24.0 // indirect
dario.cat/mergo v1.0.2 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
golang.org/x/image v0.30.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
modernc.org/libc v1.66.8 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)
require (
github.com/VictoriaMetrics/fastcache v1.10.0
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/labstack/echo-contrib v0.13.0
)
require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect
github.com/aws/smithy-go v1.23.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/disintegration/imaging v1.6.2
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.33.0
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.9
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+326 -628
View File
@@ -1,643 +1,341 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs=
github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=
github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY=
github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/casbin/casbin/v2 v2.51.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I=
github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00=
github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8=
github.com/aws/aws-sdk-go-v2/config v1.31.12/go.mod h1:/MM0dyD7KSDPR+39p9ZNVKaHDLb9qnfDurvVS2KAhN8=
github.com/aws/aws-sdk-go-v2/credentials v1.18.16 h1:4JHirI4zp958zC026Sm+V4pSDwW4pwLefKrc0bF2lwI=
github.com/aws/aws-sdk-go-v2/credentials v1.18.16/go.mod h1:qQMtGx9OSw7ty1yLclzLxXCRbrkjWAM7JnObZjmCB7I=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wgeqPL5DRFu5bQL9BGPQ8Y=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.4 h1:BTl+TXrpnrpPWb/J3527GsJ/lMkn7z3GO12j6OlsbRg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.19.4/go.mod h1:cG2tenc/fscpChiZE29a2crG9uo2t6nQGflFllFL8M8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 h1:R0tNFJqfjHL3900cqhXuwQ+1K4G0xc9Yf8EDbFXCKEw=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6/go.mod h1:y/7sDdu+aJvPtGXr4xYosdpq9a6T9Z0jkXfugmti0rI=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 h1:hncKj/4gR+TPauZgTAsxOxNcvBayhUlYZ6LO/BYiQ30=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6/go.mod h1:OiIh45tp6HdJDDJGnja0mw8ihQGz3VGrUflLqSL0SmM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 h1:nEXUSAwyUfLTgnc9cxlDWy637qsq4UWwp3sNAfl0Z3Y=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6/go.mod h1:HGzIULx4Ge3Do2V0FaiYKcyKzOqwrhUZgCI77NisswQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 h1:ETkfWcXP2KNPLecaDa++5bsQhCRa5M5sLUJa5DWYIIg=
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3/go.mod h1:+/3ZTqoYb3Ur7DObD00tarKMLMuKg8iqz5CHEanqTnw=
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 h1:A1oRkiSQOWstGh61y4Wc/yQ04sqrQZr1Si/oAXj20/s=
github.com/aws/aws-sdk-go-v2/service/sso v1.29.6/go.mod h1:5PfYspyCU5Vw1wNPsxi15LZovOnULudOQuVxphSflQA=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 h1:5fm5RTONng73/QA73LhCNR7UT9RpFH3hR6HWL6bIgVY=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1/go.mod h1:xBEjWD13h+6nq+z4AkqSfSvqRKFgDIQeaMguAJndOWo=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47hZb5HUQ0tn6Q9kA=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8=
github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ=
github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo-contrib v0.13.0 h1:bzSG0SpuZZd7BmJLvsWtPfU23W0Enh3K0tok3aENVKA=
github.com/labstack/echo-contrib v0.13.0/go.mod h1:IF9+MJu22ADOZEHD+bAV67XMIO3vNXUy7Naz/ABPHEs=
github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/labstack/echo/v5 v5.0.3 h1:Jql8sDtCYXrhh2Mbs6jKwjR6r7X8FSQQmch+w6QS7kc=
github.com/labstack/echo/v5 v5.0.3/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
github.com/testcontainers/testcontainers-go/modules/mysql v0.40.0 h1:P9Txfy5Jothx2wFdcus0QoSmX/PKSIXZxrTbZPVJswA=
github.com/testcontainers/testcontainers-go/modules/mysql v0.40.0/go.mod h1:oZPHHqJqXG7FD8OB/yWH7gLnDvZUlFHAVJNrGftL+eg=
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0 h1:s2bIayFXlbDFexo96y+htn7FzuhpXLYJNnIuglNKqOk=
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0/go.mod h1:h+u/2KoREGTnTl9UwrQ/g+XhasAT8E6dClclAADeXoQ=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220728030405-41545e8bf201 h1:bvOltf3SADAfG05iRml8lAB3qjoEX5RCyN4K6G5v3N0=
golang.org/x/net v0.0.0-20220728030405-41545e8bf201/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1 h1:APHvLLYBhtZvsbnpkfknDZ7NyH4z5+ub/I0u8L3Oz6g=
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1/go.mod h1:xUjFWUnWDpZ/C0Gu0qloASKFb6f8/QXiiXhSPFsD668=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
modernc.org/cc/v4 v4.26.4 h1:jPhG8oNjtTYuP2FA4YefTJ/wioNUGALmGuEWt7SUR6s=
modernc.org/cc/v4 v4.26.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A=
modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q=
modernc.org/fileutil v1.3.28 h1:Vp156KUA2nPu9F1NEv036x9UGOjg2qsi5QlWTjZmtMk=
modernc.org/fileutil v1.3.28/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.8 h1:/awsvTnyN/sNjvJm6S3lb7KZw5WV4ly/sBEG7ZUzmIE=
modernc.org/libc v1.66.8/go.mod h1:aVdcY7udcawRqauu0HukYYxtBSizV+R80n/6aQe9D5k=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+7
View File
@@ -0,0 +1,7 @@
package base
import "regexp"
var (
UIDMatcher = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,30}[a-zA-Z0-9])?$")
)
+35
View File
@@ -0,0 +1,35 @@
package base
import (
"testing"
)
func TestUIDMatcher(t *testing.T) {
tests := []struct {
input string
expected bool
}{
{"", false},
{"-abc123", false},
{"012345678901234567890123456789", true},
{"1abc-123", true},
{"A123B456C789", true},
{"a", true},
{"ab", true},
{"a*b&c", false},
{"a--b", true},
{"a-1b-2c", true},
{"a1234567890123456789012345678901", true},
{"abc123", true},
{"abc123-", false},
}
for _, test := range tests {
t.Run(test.input, func(*testing.T) {
result := UIDMatcher.MatchString(test.input)
if result != test.expected {
t.Errorf("For input '%s', expected %v but got %v", test.input, test.expected, result)
}
})
}
}
+107
View File
@@ -0,0 +1,107 @@
package profile
import (
"fmt"
"log/slog"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/pkg/errors"
)
// Profile is the configuration to start main server.
type Profile struct {
// Demo indicates if the server is in demo mode
Demo bool
// Addr is the binding address for server
Addr string
// Port is the binding port for server
Port int
// UNIXSock is the IPC binding path. Overrides Addr and Port
UNIXSock string
// Data is the data directory
Data string
// DSN points to where memos stores its own data
DSN string
// Driver is the database driver
// sqlite, mysql
Driver string
// Version is the current version of server
Version string
// InstanceURL is the url of your memos instance.
InstanceURL string
}
func checkDataDir(dataDir string) (string, error) {
// Convert to absolute path if relative path is supplied.
if !filepath.IsAbs(dataDir) {
// Use current working directory, not the binary's directory
// This ensures we use the actual working directory where the process runs
absDir, err := filepath.Abs(dataDir)
if err != nil {
return "", err
}
dataDir = absDir
}
// Trim trailing \ or / in case user supplies
dataDir = strings.TrimRight(dataDir, "\\/")
if _, err := os.Stat(dataDir); err != nil {
return "", errors.Wrapf(err, "unable to access data folder %s", dataDir)
}
return dataDir, nil
}
func (p *Profile) Validate() error {
// Set default data directory if not specified
if p.Data == "" {
if runtime.GOOS == "windows" {
p.Data = filepath.Join(os.Getenv("ProgramData"), "memos")
} else {
// On Linux/macOS, check if /var/opt/memos exists and is writable (Docker scenario)
if info, err := os.Stat("/var/opt/memos"); err == nil && info.IsDir() {
// Check if we can write to this directory
testFile := filepath.Join("/var/opt/memos", ".write-test")
if err := os.WriteFile(testFile, []byte("test"), 0600); err == nil {
os.Remove(testFile)
p.Data = "/var/opt/memos"
} else {
// /var/opt/memos exists but is not writable, use current directory
slog.Warn("/var/opt/memos is not writable, using current directory")
p.Data = "."
}
} else {
// /var/opt/memos doesn't exist, use current directory (local development)
p.Data = "."
}
}
}
// Create data directory if it doesn't exist
if _, err := os.Stat(p.Data); os.IsNotExist(err) {
if err := os.MkdirAll(p.Data, 0770); err != nil {
slog.Error("failed to create data directory", slog.String("data", p.Data), slog.String("error", err.Error()))
return err
}
}
dataDir, err := checkDataDir(p.Data)
if err != nil {
slog.Error("failed to check dsn", slog.String("data", dataDir), slog.String("error", err.Error()))
return err
}
p.Data = dataDir
if p.Driver == "sqlite" && p.DSN == "" {
mode := "prod"
if p.Demo {
mode = "demo"
}
dbFile := fmt.Sprintf("memos_%s.db", mode)
p.DSN = filepath.Join(dataDir, dbFile)
}
return nil
}
+73
View File
@@ -0,0 +1,73 @@
package util //nolint:revive // util namespace is intentional for shared helpers
import (
"crypto/rand"
"math/big"
"net/mail"
"strconv"
"strings"
"github.com/google/uuid"
)
// ConvertStringToInt32 converts a string to int32.
func ConvertStringToInt32(src string) (int32, error) {
parsed, err := strconv.ParseInt(src, 10, 32)
if err != nil {
return 0, err
}
return int32(parsed), nil
}
// HasPrefixes returns true if the string s has any of the given prefixes.
func HasPrefixes(src string, prefixes ...string) bool {
for _, prefix := range prefixes {
if strings.HasPrefix(src, prefix) {
return true
}
}
return false
}
// ValidateEmail validates the email.
func ValidateEmail(email string) bool {
if _, err := mail.ParseAddress(email); err != nil {
return false
}
return true
}
func GenUUID() string {
return uuid.New().String()
}
var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
// RandomString returns a random string with length n.
func RandomString(n int) (string, error) {
var sb strings.Builder
sb.Grow(n)
for i := 0; i < n; i++ {
// The reason for using crypto/rand instead of math/rand is that
// the former relies on hardware to generate random numbers and
// thus has a stronger source of random numbers.
randNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
return "", err
}
if _, err := sb.WriteRune(letters[randNum.Uint64()]); err != nil {
return "", err
}
}
return sb.String(), nil
}
// ReplaceString replaces all occurrences of old in slice with new.
func ReplaceString(slice []string, old, new string) []string {
for i, s := range slice {
if s == old {
slice[i] = new
}
}
return slice
}
@@ -1,4 +1,4 @@
package common
package util //nolint:revive // util is an appropriate package name for utility functions
import (
"testing"
@@ -14,7 +14,7 @@ func TestValidateEmail(t *testing.T) {
want: true,
},
{
email: "@qq.com",
email: "@usememos.com",
want: false,
},
{
+54
View File
@@ -0,0 +1,54 @@
package version
import (
"fmt"
"strings"
"golang.org/x/mod/semver"
)
// Version is the service current released version.
// Semantic versioning: https://semver.org/
var Version = "0.26.2"
func GetCurrentVersion() string {
return Version
}
// GetMinorVersion extracts the minor version (e.g., "0.25") from a full version string (e.g., "0.25.1").
// Returns the minor version string or empty string if the version format is invalid.
// Version format should be "major.minor.patch" (e.g., "0.25.1").
func GetMinorVersion(version string) string {
versionList := strings.Split(version, ".")
if len(versionList) < 2 {
return ""
}
// Return major.minor only (first two components)
return versionList[0] + "." + versionList[1]
}
// IsVersionGreaterOrEqualThan returns true if version is greater than or equal to target.
func IsVersionGreaterOrEqualThan(version, target string) bool {
return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1
}
// IsVersionGreaterThan returns true if version is greater than target.
func IsVersionGreaterThan(version, target string) bool {
return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0
}
type SortVersion []string
func (s SortVersion) Len() int {
return len(s)
}
func (s SortVersion) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s SortVersion) Less(i, j int) bool {
v1 := fmt.Sprintf("v%s", s[i])
v2 := fmt.Sprintf("v%s", s[j])
return semver.Compare(v1, v2) == -1
}
+103
View File
@@ -0,0 +1,103 @@
package version
import (
"sort"
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsVersionGreaterOrEqualThan(t *testing.T) {
tests := []struct {
version string
target string
want bool
}{
{
version: "0.9.1",
target: "0.9.1",
want: true,
},
{
version: "0.10.0",
target: "0.9.1",
want: true,
},
{
version: "0.9.0",
target: "0.9.1",
want: false,
},
}
for _, test := range tests {
result := IsVersionGreaterOrEqualThan(test.version, test.target)
if result != test.want {
t.Errorf("got result %v, want %v.", result, test.want)
}
}
}
func TestIsVersionGreaterThan(t *testing.T) {
tests := []struct {
version string
target string
want bool
}{
{
version: "0.9.1",
target: "0.9.1",
want: false,
},
{
version: "0.10.0",
target: "0.8.0",
want: true,
},
{
version: "0.23",
target: "0.22",
want: true,
},
{
version: "0.8.0",
target: "0.10.0",
want: false,
},
{
version: "0.9.0",
target: "0.9.1",
want: false,
},
{
version: "0.22",
target: "0.22",
want: false,
},
}
for _, test := range tests {
result := IsVersionGreaterThan(test.version, test.target)
if result != test.want {
t.Errorf("got result %v, want %v.", result, test.want)
}
}
}
func TestSortVersion(t *testing.T) {
tests := []struct {
versionList []string
want []string
}{
{
versionList: []string{"0.9.1", "0.10.0", "0.8.0"},
want: []string{"0.8.0", "0.9.1", "0.10.0"},
},
{
versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"},
want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"},
},
}
for _, test := range tests {
sort.Sort(SortVersion(test.versionList))
assert.Equal(t, test.versionList, test.want)
}
}
+1
View File
@@ -0,0 +1 @@
Fork from https://github.com/robfig/cron
+96
View File
@@ -0,0 +1,96 @@
package cron
import (
"errors"
"fmt"
"runtime"
"sync"
"time"
)
// JobWrapper decorates the given Job with some behavior.
type JobWrapper func(Job) Job
// Chain is a sequence of JobWrappers that decorates submitted jobs with
// cross-cutting behaviors like logging or synchronization.
type Chain struct {
wrappers []JobWrapper
}
// NewChain returns a Chain consisting of the given JobWrappers.
func NewChain(c ...JobWrapper) Chain {
return Chain{c}
}
// Then decorates the given job with all JobWrappers in the chain.
//
// This:
//
// NewChain(m1, m2, m3).Then(job)
//
// is equivalent to:
//
// m1(m2(m3(job)))
func (c Chain) Then(j Job) Job {
for i := range c.wrappers {
j = c.wrappers[len(c.wrappers)-i-1](j)
}
return j
}
// Recover panics in wrapped jobs and log them with the provided logger.
func Recover(logger Logger) JobWrapper {
return func(j Job) Job {
return FuncJob(func() {
defer func() {
if r := recover(); r != nil {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
err, ok := r.(error)
if !ok {
err = errors.New("panic: " + fmt.Sprint(r))
}
logger.Error(err, "panic", "stack", "...\n"+string(buf))
}
}()
j.Run()
})
}
}
// DelayIfStillRunning serializes jobs, delaying subsequent runs until the
// previous one is complete. Jobs running after a delay of more than a minute
// have the delay logged at Info.
func DelayIfStillRunning(logger Logger) JobWrapper {
return func(j Job) Job {
var mu sync.Mutex
return FuncJob(func() {
start := time.Now()
mu.Lock()
defer mu.Unlock()
if dur := time.Since(start); dur > time.Minute {
logger.Info("delay", "duration", dur)
}
j.Run()
})
}
}
// SkipIfStillRunning skips an invocation of the Job if a previous invocation is
// still running. It logs skips to the given logger at Info level.
func SkipIfStillRunning(logger Logger) JobWrapper {
return func(j Job) Job {
var ch = make(chan struct{}, 1)
ch <- struct{}{}
return FuncJob(func() {
select {
case v := <-ch:
defer func() { ch <- v }()
j.Run()
default:
logger.Info("skip")
}
})
}
}
+239
View File
@@ -0,0 +1,239 @@
//nolint:all
package cron
import (
"io"
"log"
"reflect"
"sync"
"testing"
"time"
)
func appendingJob(slice *[]int, value int) Job {
var m sync.Mutex
return FuncJob(func() {
m.Lock()
*slice = append(*slice, value)
m.Unlock()
})
}
func appendingWrapper(slice *[]int, value int) JobWrapper {
return func(j Job) Job {
return FuncJob(func() {
appendingJob(slice, value).Run()
j.Run()
})
}
}
func TestChain(t *testing.T) {
var nums []int
var (
append1 = appendingWrapper(&nums, 1)
append2 = appendingWrapper(&nums, 2)
append3 = appendingWrapper(&nums, 3)
append4 = appendingJob(&nums, 4)
)
NewChain(append1, append2, append3).Then(append4).Run()
if !reflect.DeepEqual(nums, []int{1, 2, 3, 4}) {
t.Error("unexpected order of calls:", nums)
}
}
func TestChainRecover(t *testing.T) {
panickingJob := FuncJob(func() {
panic("panickingJob panics")
})
t.Run("panic exits job by default", func(*testing.T) {
defer func() {
if err := recover(); err == nil {
t.Errorf("panic expected, but none received")
}
}()
NewChain().Then(panickingJob).
Run()
})
t.Run("Recovering JobWrapper recovers", func(*testing.T) {
NewChain(Recover(PrintfLogger(log.New(io.Discard, "", 0)))).
Then(panickingJob).
Run()
})
t.Run("composed with the *IfStillRunning wrappers", func(*testing.T) {
NewChain(Recover(PrintfLogger(log.New(io.Discard, "", 0)))).
Then(panickingJob).
Run()
})
}
type countJob struct {
m sync.Mutex
started int
done int
delay time.Duration
}
func (j *countJob) Run() {
j.m.Lock()
j.started++
j.m.Unlock()
time.Sleep(j.delay)
j.m.Lock()
j.done++
j.m.Unlock()
}
func (j *countJob) Started() int {
defer j.m.Unlock()
j.m.Lock()
return j.started
}
func (j *countJob) Done() int {
defer j.m.Unlock()
j.m.Lock()
return j.done
}
func TestChainDelayIfStillRunning(t *testing.T) {
t.Run("runs immediately", func(*testing.T) {
var j countJob
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
go wrappedJob.Run()
time.Sleep(2 * time.Millisecond) // Give the job 2ms to complete.
if c := j.Done(); c != 1 {
t.Errorf("expected job run once, immediately, got %d", c)
}
})
t.Run("second run immediate if first done", func(*testing.T) {
var j countJob
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
go func() {
go wrappedJob.Run()
time.Sleep(time.Millisecond)
go wrappedJob.Run()
}()
time.Sleep(3 * time.Millisecond) // Give both jobs 3ms to complete.
if c := j.Done(); c != 2 {
t.Errorf("expected job run twice, immediately, got %d", c)
}
})
t.Run("second run delayed if first not done", func(*testing.T) {
var j countJob
j.delay = 10 * time.Millisecond
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
go func() {
go wrappedJob.Run()
time.Sleep(time.Millisecond)
go wrappedJob.Run()
}()
// After 5ms, the first job is still in progress, and the second job was
// run but should be waiting for it to finish.
time.Sleep(5 * time.Millisecond)
started, done := j.Started(), j.Done()
if started != 1 || done != 0 {
t.Error("expected first job started, but not finished, got", started, done)
}
// Verify that the second job completes.
time.Sleep(25 * time.Millisecond)
started, done = j.Started(), j.Done()
if started != 2 || done != 2 {
t.Error("expected both jobs done, got", started, done)
}
})
}
func TestChainSkipIfStillRunning(t *testing.T) {
t.Run("runs immediately", func(*testing.T) {
var j countJob
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
go wrappedJob.Run()
time.Sleep(2 * time.Millisecond) // Give the job 2ms to complete.
if c := j.Done(); c != 1 {
t.Errorf("expected job run once, immediately, got %d", c)
}
})
t.Run("second run immediate if first done", func(*testing.T) {
var j countJob
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
go func() {
go wrappedJob.Run()
time.Sleep(time.Millisecond)
go wrappedJob.Run()
}()
time.Sleep(3 * time.Millisecond) // Give both jobs 3ms to complete.
if c := j.Done(); c != 2 {
t.Errorf("expected job run twice, immediately, got %d", c)
}
})
t.Run("second run skipped if first not done", func(*testing.T) {
var j countJob
j.delay = 10 * time.Millisecond
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
go func() {
go wrappedJob.Run()
time.Sleep(time.Millisecond)
go wrappedJob.Run()
}()
// After 5ms, the first job is still in progress, and the second job was
// already skipped.
time.Sleep(5 * time.Millisecond)
started, done := j.Started(), j.Done()
if started != 1 || done != 0 {
t.Error("expected first job started, but not finished, got", started, done)
}
// Verify that the first job completes and second does not run.
time.Sleep(25 * time.Millisecond)
started, done = j.Started(), j.Done()
if started != 1 || done != 1 {
t.Error("expected second job skipped, got", started, done)
}
})
t.Run("skip 10 jobs on rapid fire", func(*testing.T) {
var j countJob
j.delay = 10 * time.Millisecond
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
for i := 0; i < 11; i++ {
go wrappedJob.Run()
}
time.Sleep(200 * time.Millisecond)
done := j.Done()
if done != 1 {
t.Error("expected 1 jobs executed, 10 jobs dropped, got", done)
}
})
t.Run("different jobs independent", func(*testing.T) {
var j1, j2 countJob
j1.delay = 10 * time.Millisecond
j2.delay = 10 * time.Millisecond
chain := NewChain(SkipIfStillRunning(DiscardLogger))
wrappedJob1 := chain.Then(&j1)
wrappedJob2 := chain.Then(&j2)
for i := 0; i < 11; i++ {
go wrappedJob1.Run()
go wrappedJob2.Run()
}
time.Sleep(100 * time.Millisecond)
var (
done1 = j1.Done()
done2 = j2.Done()
)
if done1 != 1 || done2 != 1 {
t.Error("expected both jobs executed once, got", done1, "and", done2)
}
})
}
+27
View File
@@ -0,0 +1,27 @@
package cron
import "time"
// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
// It does not support jobs more frequent than once a second.
type ConstantDelaySchedule struct {
Delay time.Duration
}
// Every returns a crontab Schedule that activates once every duration.
// Delays of less than a second are not supported (will round up to 1 second).
// Any fields less than a Second are truncated.
func Every(duration time.Duration) ConstantDelaySchedule {
if duration < time.Second {
duration = time.Second
}
return ConstantDelaySchedule{
Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
}
}
// Next returns the next time this should be run.
// This rounds so that the next activation time will be on the second.
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
}
+55
View File
@@ -0,0 +1,55 @@
//nolint:all
package cron
import (
"testing"
"time"
)
func TestConstantDelayNext(t *testing.T) {
tests := []struct {
time string
delay time.Duration
expected string
}{
// Simple cases
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
{"Mon Jul 9 14:59 2012", 15 * time.Minute, "Mon Jul 9 15:14 2012"},
{"Mon Jul 9 14:59:59 2012", 15 * time.Minute, "Mon Jul 9 15:14:59 2012"},
// Wrap around hours
{"Mon Jul 9 15:45 2012", 35 * time.Minute, "Mon Jul 9 16:20 2012"},
// Wrap around days
{"Mon Jul 9 23:46 2012", 14 * time.Minute, "Tue Jul 10 00:00 2012"},
{"Mon Jul 9 23:45 2012", 35 * time.Minute, "Tue Jul 10 00:20 2012"},
{"Mon Jul 9 23:35:51 2012", 44*time.Minute + 24*time.Second, "Tue Jul 10 00:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", 25*time.Hour + 44*time.Minute + 24*time.Second, "Thu Jul 11 01:20:15 2012"},
// Wrap around months
{"Mon Jul 9 23:35 2012", 91*24*time.Hour + 25*time.Minute, "Thu Oct 9 00:00 2012"},
// Wrap around minute, hour, day, month, and year
{"Mon Dec 31 23:59:45 2012", 15 * time.Second, "Tue Jan 1 00:00:00 2013"},
// Round to nearest second on the delay
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
// Round up to 1 second if the duration is less.
{"Mon Jul 9 14:45:00 2012", 15 * time.Millisecond, "Mon Jul 9 14:45:01 2012"},
// Round to nearest second when calculating the next time.
{"Mon Jul 9 14:45:00.005 2012", 15 * time.Minute, "Mon Jul 9 15:00 2012"},
// Round to nearest second for both.
{"Mon Jul 9 14:45:00.005 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
}
for _, c := range tests {
actual := Every(c.delay).Next(getTime(c.time))
expected := getTime(c.expected)
if actual != expected {
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.delay, expected, actual)
}
}
}
+353
View File
@@ -0,0 +1,353 @@
package cron
import (
"context"
"sort"
"sync"
"time"
)
// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
type Cron struct {
entries []*Entry
chain Chain
stop chan struct{}
add chan *Entry
remove chan EntryID
snapshot chan chan []Entry
running bool
logger Logger
runningMu sync.Mutex
location *time.Location
parser ScheduleParser
nextID EntryID
jobWaiter sync.WaitGroup
}
// ScheduleParser is an interface for schedule spec parsers that return a Schedule.
type ScheduleParser interface {
Parse(spec string) (Schedule, error)
}
// Job is an interface for submitted cron jobs.
type Job interface {
Run()
}
// Schedule describes a job's duty cycle.
type Schedule interface {
// Next returns the next activation time, later than the given time.
// Next is invoked initially, and then each time the job is run.
Next(time.Time) time.Time
}
// EntryID identifies an entry within a Cron instance.
type EntryID int
// Entry consists of a schedule and the func to execute on that schedule.
type Entry struct {
// ID is the cron-assigned ID of this entry, which may be used to look up a
// snapshot or remove it.
ID EntryID
// Schedule on which this job should be run.
Schedule Schedule
// Next time the job will run, or the zero time if Cron has not been
// started or this entry's schedule is unsatisfiable
Next time.Time
// Prev is the last time this job was run, or the zero time if never.
Prev time.Time
// WrappedJob is the thing to run when the Schedule is activated.
WrappedJob Job
// Job is the thing that was submitted to cron.
// It is kept around so that user code that needs to get at the job later,
// e.g. via Entries() can do so.
Job Job
}
// Valid returns true if this is not the zero entry.
func (e Entry) Valid() bool { return e.ID != 0 }
// byTime is a wrapper for sorting the entry array by time
// (with zero time at the end).
type byTime []*Entry
func (s byTime) Len() int { return len(s) }
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byTime) Less(i, j int) bool {
// Two zero times should return false.
// Otherwise, zero is "greater" than any other time.
// (To sort it at the end of the list.)
if s[i].Next.IsZero() {
return false
}
if s[j].Next.IsZero() {
return true
}
return s[i].Next.Before(s[j].Next)
}
// New returns a new Cron job runner, modified by the given options.
//
// Available Settings
//
// Time Zone
// Description: The time zone in which schedules are interpreted
// Default: time.Local
//
// Parser
// Description: Parser converts cron spec strings into cron.Schedules.
// Default: Accepts this spec: https://en.wikipedia.org/wiki/Cron
//
// Chain
// Description: Wrap submitted jobs to customize behavior.
// Default: A chain that recovers panics and logs them to stderr.
//
// See "cron.With*" to modify the default behavior.
func New(opts ...Option) *Cron {
c := &Cron{
entries: nil,
chain: NewChain(),
add: make(chan *Entry),
stop: make(chan struct{}),
snapshot: make(chan chan []Entry),
remove: make(chan EntryID),
running: false,
runningMu: sync.Mutex{},
logger: DefaultLogger,
location: time.Local,
parser: standardParser,
}
for _, opt := range opts {
opt(c)
}
return c
}
// FuncJob is a wrapper that turns a func() into a cron.Job.
type FuncJob func()
func (f FuncJob) Run() { f() }
// AddFunc adds a func to the Cron to be run on the given schedule.
// The spec is parsed using the time zone of this Cron instance as the default.
// An opaque ID is returned that can be used to later remove it.
func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) {
return c.AddJob(spec, FuncJob(cmd))
}
// AddJob adds a Job to the Cron to be run on the given schedule.
// The spec is parsed using the time zone of this Cron instance as the default.
// An opaque ID is returned that can be used to later remove it.
func (c *Cron) AddJob(spec string, cmd Job) (EntryID, error) {
schedule, err := c.parser.Parse(spec)
if err != nil {
return 0, err
}
return c.Schedule(schedule, cmd), nil
}
// Schedule adds a Job to the Cron to be run on the given schedule.
// The job is wrapped with the configured Chain.
func (c *Cron) Schedule(schedule Schedule, cmd Job) EntryID {
c.runningMu.Lock()
defer c.runningMu.Unlock()
c.nextID++
entry := &Entry{
ID: c.nextID,
Schedule: schedule,
WrappedJob: c.chain.Then(cmd),
Job: cmd,
}
if !c.running {
c.entries = append(c.entries, entry)
} else {
c.add <- entry
}
return entry.ID
}
// Entries returns a snapshot of the cron entries.
func (c *Cron) Entries() []Entry {
c.runningMu.Lock()
defer c.runningMu.Unlock()
if c.running {
replyChan := make(chan []Entry, 1)
c.snapshot <- replyChan
return <-replyChan
}
return c.entrySnapshot()
}
// Location gets the time zone location.
func (c *Cron) Location() *time.Location {
return c.location
}
// Entry returns a snapshot of the given entry, or nil if it couldn't be found.
func (c *Cron) Entry(id EntryID) Entry {
for _, entry := range c.Entries() {
if id == entry.ID {
return entry
}
}
return Entry{}
}
// Remove an entry from being run in the future.
func (c *Cron) Remove(id EntryID) {
c.runningMu.Lock()
defer c.runningMu.Unlock()
if c.running {
c.remove <- id
} else {
c.removeEntry(id)
}
}
// Start the cron scheduler in its own goroutine, or no-op if already started.
func (c *Cron) Start() {
c.runningMu.Lock()
defer c.runningMu.Unlock()
if c.running {
return
}
c.running = true
go c.runScheduler()
}
// Run the cron scheduler, or no-op if already running.
func (c *Cron) Run() {
c.runningMu.Lock()
if c.running {
c.runningMu.Unlock()
return
}
c.running = true
c.runningMu.Unlock()
c.runScheduler()
}
// runScheduler runs the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) runScheduler() {
c.logger.Info("start")
// Figure out the next activation times for each entry.
now := c.now()
for _, entry := range c.entries {
entry.Next = entry.Schedule.Next(now)
c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next)
}
for {
// Determine the next entry to run.
sort.Sort(byTime(c.entries))
var timer *time.Timer
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
// If there are no entries yet, just sleep - it still handles new entries
// and stop requests.
timer = time.NewTimer(100000 * time.Hour)
} else {
timer = time.NewTimer(c.entries[0].Next.Sub(now))
}
for {
select {
case now = <-timer.C:
now = now.In(c.location)
c.logger.Info("wake", "now", now)
// Run every entry whose next time was less than now
for _, e := range c.entries {
if e.Next.After(now) || e.Next.IsZero() {
break
}
c.startJob(e.WrappedJob)
e.Prev = e.Next
e.Next = e.Schedule.Next(now)
c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)
}
case newEntry := <-c.add:
timer.Stop()
now = c.now()
newEntry.Next = newEntry.Schedule.Next(now)
c.entries = append(c.entries, newEntry)
c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next)
case replyChan := <-c.snapshot:
replyChan <- c.entrySnapshot()
continue
case <-c.stop:
timer.Stop()
c.logger.Info("stop")
return
case id := <-c.remove:
timer.Stop()
now = c.now()
c.removeEntry(id)
c.logger.Info("removed", "entry", id)
}
break
}
}
}
// startJob runs the given job in a new goroutine.
func (c *Cron) startJob(j Job) {
c.jobWaiter.Go(func() {
j.Run()
})
}
// now returns current time in c location.
func (c *Cron) now() time.Time {
return time.Now().In(c.location)
}
// Stop stops the cron scheduler if it is running; otherwise it does nothing.
// A context is returned so the caller can wait for running jobs to complete.
func (c *Cron) Stop() context.Context {
c.runningMu.Lock()
defer c.runningMu.Unlock()
if c.running {
c.stop <- struct{}{}
c.running = false
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
c.jobWaiter.Wait()
cancel()
}()
return ctx
}
// entrySnapshot returns a copy of the current cron entry list.
func (c *Cron) entrySnapshot() []Entry {
var entries = make([]Entry, len(c.entries))
for i, e := range c.entries {
entries[i] = *e
}
return entries
}
func (c *Cron) removeEntry(id EntryID) {
var entries []*Entry
for _, e := range c.entries {
if e.ID != id {
entries = append(entries, e)
}
}
c.entries = entries
}
+702
View File
@@ -0,0 +1,702 @@
//nolint:all
package cron
import (
"bytes"
"fmt"
"log"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
)
// Many tests schedule a job for every second, and then wait at most a second
// for it to run. This amount is just slightly larger than 1 second to
// compensate for a few milliseconds of runtime.
const OneSecond = 1*time.Second + 50*time.Millisecond
type syncWriter struct {
wr bytes.Buffer
m sync.Mutex
}
func (sw *syncWriter) Write(data []byte) (n int, err error) {
sw.m.Lock()
n, err = sw.wr.Write(data)
sw.m.Unlock()
return
}
func (sw *syncWriter) String() string {
sw.m.Lock()
defer sw.m.Unlock()
return sw.wr.String()
}
func newBufLogger(sw *syncWriter) Logger {
return PrintfLogger(log.New(sw, "", log.LstdFlags))
}
func TestFuncPanicRecovery(t *testing.T) {
var buf syncWriter
cron := New(WithParser(secondParser),
WithChain(Recover(newBufLogger(&buf))))
cron.Start()
defer cron.Stop()
cron.AddFunc("* * * * * ?", func() {
panic("YOLO")
})
select {
case <-time.After(OneSecond):
if !strings.Contains(buf.String(), "YOLO") {
t.Error("expected a panic to be logged, got none")
}
return
}
}
type DummyJob struct{}
func (DummyJob) Run() {
panic("YOLO")
}
func TestJobPanicRecovery(t *testing.T) {
var job DummyJob
var buf syncWriter
cron := New(WithParser(secondParser),
WithChain(Recover(newBufLogger(&buf))))
cron.Start()
defer cron.Stop()
cron.AddJob("* * * * * ?", job)
select {
case <-time.After(OneSecond):
if !strings.Contains(buf.String(), "YOLO") {
t.Error("expected a panic to be logged, got none")
}
return
}
}
// Start and stop cron with no entries.
func TestNoEntries(t *testing.T) {
cron := newWithSeconds()
cron.Start()
select {
case <-time.After(OneSecond):
t.Fatal("expected cron will be stopped immediately")
case <-stop(cron):
}
}
// Start, stop, then add an entry. Verify entry doesn't run.
func TestStopCausesJobsToNotRun(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.Start()
cron.Stop()
cron.AddFunc("* * * * * ?", func() { wg.Done() })
select {
case <-time.After(OneSecond):
// No job ran!
case <-wait(wg):
t.Fatal("expected stopped cron does not run any job")
}
}
// Add a job, start cron, expect it runs.
func TestAddBeforeRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Start()
defer cron.Stop()
// Give cron 2 seconds to run our job (which is always activated).
select {
case <-time.After(OneSecond):
t.Fatal("expected job runs")
case <-wait(wg):
}
}
// Start cron, add a job, expect it runs.
func TestAddWhileRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.Start()
defer cron.Stop()
cron.AddFunc("* * * * * ?", func() { wg.Done() })
select {
case <-time.After(OneSecond):
t.Fatal("expected job runs")
case <-wait(wg):
}
}
// Test for #34. Adding a job after calling start results in multiple job invocations
func TestAddWhileRunningWithDelay(t *testing.T) {
cron := newWithSeconds()
cron.Start()
defer cron.Stop()
time.Sleep(5 * time.Second)
var calls int64
cron.AddFunc("* * * * * *", func() { atomic.AddInt64(&calls, 1) })
<-time.After(OneSecond)
if atomic.LoadInt64(&calls) != 1 {
t.Errorf("called %d times, expected 1\n", calls)
}
}
// Add a job, remove a job, start cron, expect nothing runs.
func TestRemoveBeforeRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
id, _ := cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Remove(id)
cron.Start()
defer cron.Stop()
select {
case <-time.After(OneSecond):
// Success, shouldn't run
case <-wait(wg):
t.FailNow()
}
}
// Start cron, add a job, remove it, expect it doesn't run.
func TestRemoveWhileRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.Start()
defer cron.Stop()
id, _ := cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Remove(id)
select {
case <-time.After(OneSecond):
case <-wait(wg):
t.FailNow()
}
}
// Test timing with Entries.
func TestSnapshotEntries(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.AddFunc("@every 2s", func() { wg.Done() })
cron.Start()
defer cron.Stop()
// Cron should fire in 2 seconds. After 1 second, call Entries.
select {
case <-time.After(OneSecond):
cron.Entries()
}
// Even though Entries was called, the cron should fire at the 2 second mark.
select {
case <-time.After(OneSecond):
t.Error("expected job runs at 2 second mark")
case <-wait(wg):
}
}
// Test that the entries are correctly sorted.
// Add a bunch of long-in-the-future entries, and an immediate entry, and ensure
// that the immediate entry runs immediately.
// Also: Test that multiple jobs run in the same instant.
func TestMultipleEntries(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := newWithSeconds()
cron.AddFunc("0 0 0 1 1 ?", func() {})
cron.AddFunc("* * * * * ?", func() { wg.Done() })
id1, _ := cron.AddFunc("* * * * * ?", func() { t.Fatal() })
id2, _ := cron.AddFunc("* * * * * ?", func() { t.Fatal() })
cron.AddFunc("0 0 0 31 12 ?", func() {})
cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Remove(id1)
cron.Start()
cron.Remove(id2)
defer cron.Stop()
select {
case <-time.After(OneSecond):
t.Error("expected job run in proper order")
case <-wait(wg):
}
}
// Test running the same job twice.
func TestRunningJobTwice(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := newWithSeconds()
cron.AddFunc("0 0 0 1 1 ?", func() {})
cron.AddFunc("0 0 0 31 12 ?", func() {})
cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(2 * OneSecond):
t.Error("expected job fires 2 times")
case <-wait(wg):
}
}
func TestRunningMultipleSchedules(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := newWithSeconds()
cron.AddFunc("0 0 0 1 1 ?", func() {})
cron.AddFunc("0 0 0 31 12 ?", func() {})
cron.AddFunc("* * * * * ?", func() { wg.Done() })
cron.Schedule(Every(time.Minute), FuncJob(func() {}))
cron.Schedule(Every(time.Second), FuncJob(func() { wg.Done() }))
cron.Schedule(Every(time.Hour), FuncJob(func() {}))
cron.Start()
defer cron.Stop()
select {
case <-time.After(2 * OneSecond):
t.Error("expected job fires 2 times")
case <-wait(wg):
}
}
// Test that the cron is run in the local time zone (as opposed to UTC).
func TestLocalTimezone(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
now := time.Now()
// FIX: Issue #205
// This calculation doesn't work in seconds 58 or 59.
// Take the easy way out and sleep.
if now.Second() >= 58 {
time.Sleep(2 * time.Second)
now = time.Now()
}
spec := fmt.Sprintf("%d,%d %d %d %d %d ?",
now.Second()+1, now.Second()+2, now.Minute(), now.Hour(), now.Day(), now.Month())
cron := newWithSeconds()
cron.AddFunc(spec, func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(OneSecond * 2):
t.Error("expected job fires 2 times")
case <-wait(wg):
}
}
// Test that the cron is run in the given time zone (as opposed to local).
func TestNonLocalTimezone(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
loc, err := time.LoadLocation("Atlantic/Cape_Verde")
if err != nil {
fmt.Printf("Failed to load time zone Atlantic/Cape_Verde: %+v", err)
t.Fail()
}
now := time.Now().In(loc)
// FIX: Issue #205
// This calculation doesn't work in seconds 58 or 59.
// Take the easy way out and sleep.
if now.Second() >= 58 {
time.Sleep(2 * time.Second)
now = time.Now().In(loc)
}
spec := fmt.Sprintf("%d,%d %d %d %d %d ?",
now.Second()+1, now.Second()+2, now.Minute(), now.Hour(), now.Day(), now.Month())
cron := New(WithLocation(loc), WithParser(secondParser))
cron.AddFunc(spec, func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(OneSecond * 2):
t.Error("expected job fires 2 times")
case <-wait(wg):
}
}
// Test that calling stop before start silently returns without
// blocking the stop channel.
func TestStopWithoutStart(t *testing.T) {
cron := New()
cron.Stop()
}
type testJob struct {
wg *sync.WaitGroup
name string
}
func (t testJob) Run() {
t.wg.Done()
}
// Test that adding an invalid job spec returns an error
func TestInvalidJobSpec(t *testing.T) {
cron := New()
_, err := cron.AddJob("this will not parse", nil)
if err == nil {
t.Errorf("expected an error with invalid spec, got nil")
}
}
// Test blocking run method behaves as Start()
func TestBlockingRun(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.AddFunc("* * * * * ?", func() { wg.Done() })
var unblockChan = make(chan struct{})
go func() {
cron.Run()
close(unblockChan)
}()
defer cron.Stop()
select {
case <-time.After(OneSecond):
t.Error("expected job fires")
case <-unblockChan:
t.Error("expected that Run() blocks")
case <-wait(wg):
}
}
// Test that double-running is a no-op
func TestStartNoop(t *testing.T) {
var tickChan = make(chan struct{}, 2)
cron := newWithSeconds()
cron.AddFunc("* * * * * ?", func() {
tickChan <- struct{}{}
})
cron.Start()
defer cron.Stop()
// Wait for the first firing to ensure the runner is going
<-tickChan
cron.Start()
<-tickChan
// Fail if this job fires again in a short period, indicating a double-run
select {
case <-time.After(time.Millisecond):
case <-tickChan:
t.Error("expected job fires exactly twice")
}
}
// Simple test using Runnables.
func TestJob(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := newWithSeconds()
cron.AddJob("0 0 0 30 Feb ?", testJob{wg, "job0"})
cron.AddJob("0 0 0 1 1 ?", testJob{wg, "job1"})
job2, _ := cron.AddJob("* * * * * ?", testJob{wg, "job2"})
cron.AddJob("1 0 0 1 1 ?", testJob{wg, "job3"})
cron.Schedule(Every(5*time.Second+5*time.Nanosecond), testJob{wg, "job4"})
job5 := cron.Schedule(Every(5*time.Minute), testJob{wg, "job5"})
// Test getting an Entry pre-Start.
if actualName := cron.Entry(job2).Job.(testJob).name; actualName != "job2" {
t.Error("wrong job retrieved:", actualName)
}
if actualName := cron.Entry(job5).Job.(testJob).name; actualName != "job5" {
t.Error("wrong job retrieved:", actualName)
}
cron.Start()
defer cron.Stop()
select {
case <-time.After(OneSecond):
t.FailNow()
case <-wait(wg):
}
// Ensure the entries are in the right order.
expecteds := []string{"job2", "job4", "job5", "job1", "job3", "job0"}
var actuals []string
for _, entry := range cron.Entries() {
actuals = append(actuals, entry.Job.(testJob).name)
}
for i, expected := range expecteds {
if actuals[i] != expected {
t.Fatalf("Jobs not in the right order. (expected) %s != %s (actual)", expecteds, actuals)
}
}
// Test getting Entries.
if actualName := cron.Entry(job2).Job.(testJob).name; actualName != "job2" {
t.Error("wrong job retrieved:", actualName)
}
if actualName := cron.Entry(job5).Job.(testJob).name; actualName != "job5" {
t.Error("wrong job retrieved:", actualName)
}
}
// Issue #206
// Ensure that the next run of a job after removing an entry is accurate.
func TestScheduleAfterRemoval(t *testing.T) {
var wg1 sync.WaitGroup
var wg2 sync.WaitGroup
wg1.Add(1)
wg2.Add(1)
// The first time this job is run, set a timer and remove the other job
// 750ms later. Correct behavior would be to still run the job again in
// 250ms, but the bug would cause it to run instead 1s later.
var calls int
var mu sync.Mutex
cron := newWithSeconds()
hourJob := cron.Schedule(Every(time.Hour), FuncJob(func() {}))
cron.Schedule(Every(time.Second), FuncJob(func() {
mu.Lock()
defer mu.Unlock()
switch calls {
case 0:
wg1.Done()
calls++
case 1:
time.Sleep(750 * time.Millisecond)
cron.Remove(hourJob)
calls++
case 2:
calls++
wg2.Done()
case 3:
panic("unexpected 3rd call")
}
}))
cron.Start()
defer cron.Stop()
// the first run might be any length of time 0 - 1s, since the schedule
// rounds to the second. wait for the first run to true up.
wg1.Wait()
select {
case <-time.After(2 * OneSecond):
t.Error("expected job fires 2 times")
case <-wait(&wg2):
}
}
type ZeroSchedule struct{}
func (*ZeroSchedule) Next(time.Time) time.Time {
return time.Time{}
}
// Tests that job without time does not run
func TestJobWithZeroTimeDoesNotRun(t *testing.T) {
cron := newWithSeconds()
var calls int64
cron.AddFunc("* * * * * *", func() { atomic.AddInt64(&calls, 1) })
cron.Schedule(new(ZeroSchedule), FuncJob(func() { t.Error("expected zero task will not run") }))
cron.Start()
defer cron.Stop()
<-time.After(OneSecond)
if atomic.LoadInt64(&calls) != 1 {
t.Errorf("called %d times, expected 1\n", calls)
}
}
func TestStopAndWait(t *testing.T) {
t.Run("nothing running, returns immediately", func(*testing.T) {
cron := newWithSeconds()
cron.Start()
ctx := cron.Stop()
select {
case <-ctx.Done():
case <-time.After(time.Millisecond):
t.Error("context was not done immediately")
}
})
t.Run("repeated calls to Stop", func(*testing.T) {
cron := newWithSeconds()
cron.Start()
_ = cron.Stop()
time.Sleep(time.Millisecond)
ctx := cron.Stop()
select {
case <-ctx.Done():
case <-time.After(time.Millisecond):
t.Error("context was not done immediately")
}
})
t.Run("a couple fast jobs added, still returns immediately", func(*testing.T) {
cron := newWithSeconds()
cron.AddFunc("* * * * * *", func() {})
cron.Start()
cron.AddFunc("* * * * * *", func() {})
cron.AddFunc("* * * * * *", func() {})
cron.AddFunc("* * * * * *", func() {})
time.Sleep(time.Second)
ctx := cron.Stop()
select {
case <-ctx.Done():
case <-time.After(time.Millisecond):
t.Error("context was not done immediately")
}
})
t.Run("a couple fast jobs and a slow job added, waits for slow job", func(*testing.T) {
cron := newWithSeconds()
cron.AddFunc("* * * * * *", func() {})
cron.Start()
cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
cron.AddFunc("* * * * * *", func() {})
time.Sleep(time.Second)
ctx := cron.Stop()
// Verify that it is not done for at least 750ms
select {
case <-ctx.Done():
t.Error("context was done too quickly immediately")
case <-time.After(750 * time.Millisecond):
// expected, because the job sleeping for 1 second is still running
}
// Verify that it IS done in the next 500ms (giving 250ms buffer)
select {
case <-ctx.Done():
// expected
case <-time.After(1500 * time.Millisecond):
t.Error("context not done after job should have completed")
}
})
t.Run("repeated calls to stop, waiting for completion and after", func(*testing.T) {
cron := newWithSeconds()
cron.AddFunc("* * * * * *", func() {})
cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
cron.Start()
cron.AddFunc("* * * * * *", func() {})
time.Sleep(time.Second)
ctx := cron.Stop()
ctx2 := cron.Stop()
// Verify that it is not done for at least 1500ms
select {
case <-ctx.Done():
t.Error("context was done too quickly immediately")
case <-ctx2.Done():
t.Error("context2 was done too quickly immediately")
case <-time.After(1500 * time.Millisecond):
// expected, because the job sleeping for 2 seconds is still running
}
// Verify that it IS done in the next 1s (giving 500ms buffer)
select {
case <-ctx.Done():
// expected
case <-time.After(time.Second):
t.Error("context not done after job should have completed")
}
// Verify that ctx2 is also done.
select {
case <-ctx2.Done():
// expected
case <-time.After(time.Millisecond):
t.Error("context2 not done even though context1 is")
}
// Verify that a new context retrieved from stop is immediately done.
ctx3 := cron.Stop()
select {
case <-ctx3.Done():
// expected
case <-time.After(time.Millisecond):
t.Error("context not done even when cron Stop is completed")
}
})
}
func TestMultiThreadedStartAndStop(t *testing.T) {
cron := New()
go cron.Run()
time.Sleep(2 * time.Millisecond)
cron.Stop()
}
func wait(wg *sync.WaitGroup) chan bool {
ch := make(chan bool)
go func() {
wg.Wait()
ch <- true
}()
return ch
}
func stop(cron *Cron) chan bool {
ch := make(chan bool)
go func() {
cron.Stop()
ch <- true
}()
return ch
}
// newWithSeconds returns a Cron with the seconds field enabled.
func newWithSeconds() *Cron {
return New(WithParser(secondParser), WithChain())
}
+86
View File
@@ -0,0 +1,86 @@
package cron
import (
"io"
"log"
"os"
"strings"
"time"
)
// DefaultLogger is used by Cron if none is specified.
var DefaultLogger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
// DiscardLogger can be used by callers to discard all log messages.
var DiscardLogger = PrintfLogger(log.New(io.Discard, "", 0))
// Logger is the interface used in this package for logging, so that any backend
// can be plugged in. It is a subset of the github.com/go-logr/logr interface.
type Logger interface {
// Info logs routine messages about cron's operation.
Info(msg string, keysAndValues ...interface{})
// Error logs an error condition.
Error(err error, msg string, keysAndValues ...interface{})
}
// PrintfLogger wraps a Printf-based logger (such as the standard library "log")
// into an implementation of the Logger interface which logs errors only.
func PrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
return printfLogger{l, false}
}
// VerbosePrintfLogger wraps a Printf-based logger (such as the standard library
// "log") into an implementation of the Logger interface which logs everything.
func VerbosePrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
return printfLogger{l, true}
}
type printfLogger struct {
logger interface{ Printf(string, ...interface{}) }
logInfo bool
}
func (pl printfLogger) Info(msg string, keysAndValues ...interface{}) {
if pl.logInfo {
keysAndValues = formatTimes(keysAndValues)
pl.logger.Printf(
formatString(len(keysAndValues)),
append([]interface{}{msg}, keysAndValues...)...)
}
}
func (pl printfLogger) Error(err error, msg string, keysAndValues ...interface{}) {
keysAndValues = formatTimes(keysAndValues)
pl.logger.Printf(
formatString(len(keysAndValues)+2),
append([]interface{}{msg, "error", err}, keysAndValues...)...)
}
// formatString returns a logfmt-like format string for the number of
// key/values.
func formatString(numKeysAndValues int) string {
var sb strings.Builder
sb.WriteString("%s")
if numKeysAndValues > 0 {
sb.WriteString(", ")
}
for i := 0; i < numKeysAndValues/2; i++ {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString("%v=%v")
}
return sb.String()
}
// formatTimes formats any time.Time values as RFC3339.
func formatTimes(keysAndValues []interface{}) []interface{} {
var formattedArgs []interface{}
for _, arg := range keysAndValues {
if t, ok := arg.(time.Time); ok {
arg = t.Format(time.RFC3339)
}
formattedArgs = append(formattedArgs, arg)
}
return formattedArgs
}
+45
View File
@@ -0,0 +1,45 @@
package cron
import (
"time"
)
// Option represents a modification to the default behavior of a Cron.
type Option func(*Cron)
// WithLocation overrides the timezone of the cron instance.
func WithLocation(loc *time.Location) Option {
return func(c *Cron) {
c.location = loc
}
}
// WithSeconds overrides the parser used for interpreting job schedules to
// include a seconds field as the first one.
func WithSeconds() Option {
return WithParser(NewParser(
Second | Minute | Hour | Dom | Month | Dow | Descriptor,
))
}
// WithParser overrides the parser used for interpreting job schedules.
func WithParser(p ScheduleParser) Option {
return func(c *Cron) {
c.parser = p
}
}
// WithChain specifies Job wrappers to apply to all jobs added to this cron.
// Refer to the Chain* functions in this package for provided wrappers.
func WithChain(wrappers ...JobWrapper) Option {
return func(c *Cron) {
c.chain = NewChain(wrappers...)
}
}
// WithLogger uses the provided logger.
func WithLogger(logger Logger) Option {
return func(c *Cron) {
c.logger = logger
}
}
+43
View File
@@ -0,0 +1,43 @@
//nolint:all
package cron
import (
"log"
"strings"
"testing"
"time"
)
func TestWithLocation(t *testing.T) {
c := New(WithLocation(time.UTC))
if c.location != time.UTC {
t.Errorf("expected UTC, got %v", c.location)
}
}
func TestWithParser(t *testing.T) {
var parser = NewParser(Dow)
c := New(WithParser(parser))
if c.parser != parser {
t.Error("expected provided parser")
}
}
func TestWithVerboseLogger(t *testing.T) {
var buf syncWriter
var logger = log.New(&buf, "", log.LstdFlags)
c := New(WithLogger(VerbosePrintfLogger(logger)))
if c.logger.(printfLogger).logger != logger {
t.Error("expected provided logger")
}
c.AddFunc("@every 1s", func() {})
c.Start()
time.Sleep(OneSecond)
c.Stop()
out := buf.String()
if !strings.Contains(out, "schedule,") ||
!strings.Contains(out, "run,") {
t.Error("expected to see some actions, got:", out)
}
}
+437
View File
@@ -0,0 +1,437 @@
package cron
import (
"math"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
)
// Configuration options for creating a parser. Most options specify which
// fields should be included, while others enable features. If a field is not
// included the parser will assume a default value. These options do not change
// the order fields are parse in.
type ParseOption int
const (
Second ParseOption = 1 << iota // Seconds field, default 0
SecondOptional // Optional seconds field, default 0
Minute // Minutes field, default 0
Hour // Hours field, default 0
Dom // Day of month field, default *
Month // Month field, default *
Dow // Day of week field, default *
DowOptional // Optional day of week field, default *
Descriptor // Allow descriptors such as @monthly, @weekly, etc.
)
var places = []ParseOption{
Second,
Minute,
Hour,
Dom,
Month,
Dow,
}
var defaults = []string{
"0",
"0",
"0",
"*",
"*",
"*",
}
// A custom Parser that can be configured.
type Parser struct {
options ParseOption
}
// NewParser creates a Parser with custom options.
//
// It panics if more than one Optional is given, since it would be impossible to
// correctly infer which optional is provided or missing in general.
//
// Examples
//
// // Standard parser without descriptors
// specParser := NewParser(Minute | Hour | Dom | Month | Dow)
// sched, err := specParser.Parse("0 0 15 */3 *")
//
// // Same as above, just excludes time fields
// specParser := NewParser(Dom | Month | Dow)
// sched, err := specParser.Parse("15 */3 *")
//
// // Same as above, just makes Dow optional
// specParser := NewParser(Dom | Month | DowOptional)
// sched, err := specParser.Parse("15 */3")
func NewParser(options ParseOption) Parser {
optionals := 0
if options&DowOptional > 0 {
optionals++
}
if options&SecondOptional > 0 {
optionals++
}
if optionals > 1 {
panic("multiple optionals may not be configured")
}
return Parser{options}
}
// Parse returns a new crontab schedule representing the given spec.
// It returns a descriptive error if the spec is not valid.
// It accepts crontab specs and features configured by NewParser.
func (p Parser) Parse(spec string) (Schedule, error) {
if len(spec) == 0 {
return nil, errors.New("empty spec string")
}
// Extract timezone if present
var loc = time.Local
if strings.HasPrefix(spec, "TZ=") || strings.HasPrefix(spec, "CRON_TZ=") {
var err error
i := strings.Index(spec, " ")
eq := strings.Index(spec, "=")
if loc, err = time.LoadLocation(spec[eq+1 : i]); err != nil {
return nil, errors.Wrap(err, "provided bad location")
}
spec = strings.TrimSpace(spec[i:])
}
// Handle named schedules (descriptors), if configured
if strings.HasPrefix(spec, "@") {
if p.options&Descriptor == 0 {
return nil, errors.New("descriptors not enabled")
}
return parseDescriptor(spec, loc)
}
// Split on whitespace.
fields := strings.Fields(spec)
// Validate & fill in any omitted or optional fields
var err error
fields, err = normalizeFields(fields, p.options)
if err != nil {
return nil, err
}
field := func(field string, r bounds) uint64 {
if err != nil {
return 0
}
var bits uint64
bits, err = getField(field, r)
return bits
}
var (
second = field(fields[0], seconds)
minute = field(fields[1], minutes)
hour = field(fields[2], hours)
dayofmonth = field(fields[3], dom)
month = field(fields[4], months)
dayofweek = field(fields[5], dow)
)
if err != nil {
return nil, err
}
return &SpecSchedule{
Second: second,
Minute: minute,
Hour: hour,
Dom: dayofmonth,
Month: month,
Dow: dayofweek,
Location: loc,
}, nil
}
// normalizeFields takes a subset set of the time fields and returns the full set
// with defaults (zeroes) populated for unset fields.
//
// As part of performing this function, it also validates that the provided
// fields are compatible with the configured options.
func normalizeFields(fields []string, options ParseOption) ([]string, error) {
// Validate optionals & add their field to options
optionals := 0
if options&SecondOptional > 0 {
options |= Second
optionals++
}
if options&DowOptional > 0 {
options |= Dow
optionals++
}
if optionals > 1 {
return nil, errors.New("multiple optionals may not be configured")
}
// Figure out how many fields we need
max := 0
for _, place := range places {
if options&place > 0 {
max++
}
}
min := max - optionals
// Validate number of fields
if count := len(fields); count < min || count > max {
if min == max {
return nil, errors.New("incorrect number of fields")
}
return nil, errors.New("incorrect number of fields, expected " + strconv.Itoa(min) + "-" + strconv.Itoa(max))
}
// Populate the optional field if not provided
if min < max && len(fields) == min {
switch {
case options&DowOptional > 0:
fields = append(fields, defaults[5]) // TODO: improve access to default
case options&SecondOptional > 0:
fields = append([]string{defaults[0]}, fields...)
default:
return nil, errors.New("unexpected optional field")
}
}
// Populate all fields not part of options with their defaults
n := 0
expandedFields := make([]string, len(places))
copy(expandedFields, defaults)
for i, place := range places {
if options&place > 0 {
expandedFields[i] = fields[n]
n++
}
}
return expandedFields, nil
}
var standardParser = NewParser(
Minute | Hour | Dom | Month | Dow | Descriptor,
)
// ParseStandard returns a new crontab schedule representing the given
// standardSpec (https://en.wikipedia.org/wiki/Cron). It requires 5 entries
// representing: minute, hour, day of month, month and day of week, in that
// order. It returns a descriptive error if the spec is not valid.
//
// It accepts
// - Standard crontab specs, e.g. "* * * * ?"
// - Descriptors, e.g. "@midnight", "@every 1h30m"
func ParseStandard(standardSpec string) (Schedule, error) {
return standardParser.Parse(standardSpec)
}
// getField returns an Int with the bits set representing all of the times that
// the field represents or error parsing field value. A "field" is a comma-separated
// list of "ranges".
func getField(field string, r bounds) (uint64, error) {
var bits uint64
ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
for _, expr := range ranges {
bit, err := getRange(expr, r)
if err != nil {
return bits, err
}
bits |= bit
}
return bits, nil
}
// getRange returns the bits indicated by the given expression:
//
// number | number "-" number [ "/" number ]
//
// or error parsing range.
func getRange(expr string, r bounds) (uint64, error) {
var (
start, end, step uint
rangeAndStep = strings.Split(expr, "/")
lowAndHigh = strings.Split(rangeAndStep[0], "-")
singleDigit = len(lowAndHigh) == 1
err error
)
var extra uint64
if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
start = r.min
end = r.max
extra = starBit
} else {
start, err = parseIntOrName(lowAndHigh[0], r.names)
if err != nil {
return 0, err
}
switch len(lowAndHigh) {
case 1:
end = start
case 2:
end, err = parseIntOrName(lowAndHigh[1], r.names)
if err != nil {
return 0, err
}
default:
return 0, errors.New("too many hyphens: " + expr)
}
}
switch len(rangeAndStep) {
case 1:
step = 1
case 2:
step, err = mustParseInt(rangeAndStep[1])
if err != nil {
return 0, err
}
// Special handling: "N/step" means "N-max/step".
if singleDigit {
end = r.max
}
if step > 1 {
extra = 0
}
default:
return 0, errors.New("too many slashes: " + expr)
}
if start < r.min {
return 0, errors.New("beginning of range below minimum: " + expr)
}
if end > r.max {
return 0, errors.New("end of range above maximum: " + expr)
}
if start > end {
return 0, errors.New("beginning of range after end: " + expr)
}
if step == 0 {
return 0, errors.New("step cannot be zero: " + expr)
}
return getBits(start, end, step) | extra, nil
}
// parseIntOrName returns the (possibly-named) integer contained in expr.
func parseIntOrName(expr string, names map[string]uint) (uint, error) {
if names != nil {
if namedInt, ok := names[strings.ToLower(expr)]; ok {
return namedInt, nil
}
}
return mustParseInt(expr)
}
// mustParseInt parses the given expression as an int or returns an error.
func mustParseInt(expr string) (uint, error) {
num, err := strconv.Atoi(expr)
if err != nil {
return 0, errors.Wrap(err, "failed to parse number")
}
if num < 0 {
return 0, errors.New("number must be positive")
}
return uint(num), nil
}
// getBits sets all bits in the range [min, max], modulo the given step size.
func getBits(min, max, step uint) uint64 {
var bits uint64
// If step is 1, use shifts.
if step == 1 {
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
}
// Else, use a simple loop.
for i := min; i <= max; i += step {
bits |= 1 << i
}
return bits
}
// all returns all bits within the given bounds.
func all(r bounds) uint64 {
return getBits(r.min, r.max, 1) | starBit
}
// parseDescriptor returns a predefined schedule for the expression, or error if none matches.
func parseDescriptor(descriptor string, loc *time.Location) (Schedule, error) {
switch descriptor {
case "@yearly", "@annually":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: 1 << months.min,
Dow: all(dow),
Location: loc,
}, nil
case "@monthly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: all(months),
Dow: all(dow),
Location: loc,
}, nil
case "@weekly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: 1 << dow.min,
Location: loc,
}, nil
case "@daily", "@midnight":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: all(dow),
Location: loc,
}, nil
case "@hourly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: all(hours),
Dom: all(dom),
Month: all(months),
Dow: all(dow),
Location: loc,
}, nil
default:
// Continue to check @every prefix below
}
const every = "@every "
if strings.HasPrefix(descriptor, every) {
duration, err := time.ParseDuration(descriptor[len(every):])
if err != nil {
return nil, errors.Wrap(err, "failed to parse duration")
}
return Every(duration), nil
}
return nil, errors.New("unrecognized descriptor: " + descriptor)
}
+384
View File
@@ -0,0 +1,384 @@
//nolint:all
package cron
import (
"reflect"
"strings"
"testing"
"time"
)
var secondParser = NewParser(Second | Minute | Hour | Dom | Month | DowOptional | Descriptor)
func TestRange(t *testing.T) {
zero := uint64(0)
ranges := []struct {
expr string
min, max uint
expected uint64
err string
}{
{"5", 0, 7, 1 << 5, ""},
{"0", 0, 7, 1 << 0, ""},
{"7", 0, 7, 1 << 7, ""},
{"5-5", 0, 7, 1 << 5, ""},
{"5-6", 0, 7, 1<<5 | 1<<6, ""},
{"5-7", 0, 7, 1<<5 | 1<<6 | 1<<7, ""},
{"5-6/2", 0, 7, 1 << 5, ""},
{"5-7/2", 0, 7, 1<<5 | 1<<7, ""},
{"5-7/1", 0, 7, 1<<5 | 1<<6 | 1<<7, ""},
{"*", 1, 3, 1<<1 | 1<<2 | 1<<3 | starBit, ""},
{"*/2", 1, 3, 1<<1 | 1<<3, ""},
{"5--5", 0, 0, zero, "too many hyphens"},
{"jan-x", 0, 0, zero, `failed to parse number: strconv.Atoi: parsing "jan": invalid syntax`},
{"2-x", 1, 5, zero, `failed to parse number: strconv.Atoi: parsing "x": invalid syntax`},
{"*/-12", 0, 0, zero, "number must be positive"},
{"*//2", 0, 0, zero, "too many slashes"},
{"1", 3, 5, zero, "below minimum"},
{"6", 3, 5, zero, "above maximum"},
{"5-3", 3, 5, zero, "beginning of range after end: 5-3"},
{"*/0", 0, 0, zero, "step cannot be zero: */0"},
}
for _, c := range ranges {
actual, err := getRange(c.expr, bounds{c.min, c.max, nil})
if len(c.err) != 0 && (err == nil || !strings.Contains(err.Error(), c.err)) {
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
}
if len(c.err) == 0 && err != nil {
t.Errorf("%s => unexpected error %v", c.expr, err)
}
if actual != c.expected {
t.Errorf("%s => expected %d, got %d", c.expr, c.expected, actual)
}
}
}
func TestField(t *testing.T) {
fields := []struct {
expr string
min, max uint
expected uint64
}{
{"5", 1, 7, 1 << 5},
{"5,6", 1, 7, 1<<5 | 1<<6},
{"5,6,7", 1, 7, 1<<5 | 1<<6 | 1<<7},
{"1,5-7/2,3", 1, 7, 1<<1 | 1<<5 | 1<<7 | 1<<3},
}
for _, c := range fields {
actual, _ := getField(c.expr, bounds{c.min, c.max, nil})
if actual != c.expected {
t.Errorf("%s => expected %d, got %d", c.expr, c.expected, actual)
}
}
}
func TestAll(t *testing.T) {
allBits := []struct {
r bounds
expected uint64
}{
{minutes, 0xfffffffffffffff}, // 0-59: 60 ones
{hours, 0xffffff}, // 0-23: 24 ones
{dom, 0xfffffffe}, // 1-31: 31 ones, 1 zero
{months, 0x1ffe}, // 1-12: 12 ones, 1 zero
{dow, 0x7f}, // 0-6: 7 ones
}
for _, c := range allBits {
actual := all(c.r) // all() adds the starBit, so compensate for that..
if c.expected|starBit != actual {
t.Errorf("%d-%d/%d => expected %b, got %b",
c.r.min, c.r.max, 1, c.expected|starBit, actual)
}
}
}
func TestBits(t *testing.T) {
bits := []struct {
min, max, step uint
expected uint64
}{
{0, 0, 1, 0x1},
{1, 1, 1, 0x2},
{1, 5, 2, 0x2a}, // 101010
{1, 4, 2, 0xa}, // 1010
}
for _, c := range bits {
actual := getBits(c.min, c.max, c.step)
if c.expected != actual {
t.Errorf("%d-%d/%d => expected %b, got %b",
c.min, c.max, c.step, c.expected, actual)
}
}
}
func TestParseScheduleErrors(t *testing.T) {
var tests = []struct{ expr, err string }{
{"* 5 j * * *", `failed to parse number: strconv.Atoi: parsing "j": invalid syntax`},
{"@every Xm", "failed to parse duration"},
{"@unrecognized", "unrecognized descriptor"},
{"* * * *", "incorrect number of fields, expected 5-6"},
{"", "empty spec string"},
}
for _, c := range tests {
actual, err := secondParser.Parse(c.expr)
if err == nil || !strings.Contains(err.Error(), c.err) {
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
}
if actual != nil {
t.Errorf("expected nil schedule on error, got %v", actual)
}
}
}
func TestParseSchedule(t *testing.T) {
tokyo, _ := time.LoadLocation("Asia/Tokyo")
entries := []struct {
parser Parser
expr string
expected Schedule
}{
{secondParser, "0 5 * * * *", every5min(time.Local)},
{standardParser, "5 * * * *", every5min(time.Local)},
{secondParser, "CRON_TZ=UTC 0 5 * * * *", every5min(time.UTC)},
{standardParser, "CRON_TZ=UTC 5 * * * *", every5min(time.UTC)},
{secondParser, "CRON_TZ=Asia/Tokyo 0 5 * * * *", every5min(tokyo)},
{secondParser, "@every 5m", ConstantDelaySchedule{5 * time.Minute}},
{secondParser, "@midnight", midnight(time.Local)},
{secondParser, "TZ=UTC @midnight", midnight(time.UTC)},
{secondParser, "TZ=Asia/Tokyo @midnight", midnight(tokyo)},
{secondParser, "@yearly", annual(time.Local)},
{secondParser, "@annually", annual(time.Local)},
{
parser: secondParser,
expr: "* 5 * * * *",
expected: &SpecSchedule{
Second: all(seconds),
Minute: 1 << 5,
Hour: all(hours),
Dom: all(dom),
Month: all(months),
Dow: all(dow),
Location: time.Local,
},
},
}
for _, c := range entries {
actual, err := c.parser.Parse(c.expr)
if err != nil {
t.Errorf("%s => unexpected error %v", c.expr, err)
}
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
}
}
}
func TestOptionalSecondSchedule(t *testing.T) {
parser := NewParser(SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor)
entries := []struct {
expr string
expected Schedule
}{
{"0 5 * * * *", every5min(time.Local)},
{"5 5 * * * *", every5min5s(time.Local)},
{"5 * * * *", every5min(time.Local)},
}
for _, c := range entries {
actual, err := parser.Parse(c.expr)
if err != nil {
t.Errorf("%s => unexpected error %v", c.expr, err)
}
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
}
}
}
func TestNormalizeFields(t *testing.T) {
tests := []struct {
name string
input []string
options ParseOption
expected []string
}{
{
"AllFields_NoOptional",
[]string{"0", "5", "*", "*", "*", "*"},
Second | Minute | Hour | Dom | Month | Dow | Descriptor,
[]string{"0", "5", "*", "*", "*", "*"},
},
{
"AllFields_SecondOptional_Provided",
[]string{"0", "5", "*", "*", "*", "*"},
SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor,
[]string{"0", "5", "*", "*", "*", "*"},
},
{
"AllFields_SecondOptional_NotProvided",
[]string{"5", "*", "*", "*", "*"},
SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor,
[]string{"0", "5", "*", "*", "*", "*"},
},
{
"SubsetFields_NoOptional",
[]string{"5", "15", "*"},
Hour | Dom | Month,
[]string{"0", "0", "5", "15", "*", "*"},
},
{
"SubsetFields_DowOptional_Provided",
[]string{"5", "15", "*", "4"},
Hour | Dom | Month | DowOptional,
[]string{"0", "0", "5", "15", "*", "4"},
},
{
"SubsetFields_DowOptional_NotProvided",
[]string{"5", "15", "*"},
Hour | Dom | Month | DowOptional,
[]string{"0", "0", "5", "15", "*", "*"},
},
{
"SubsetFields_SecondOptional_NotProvided",
[]string{"5", "15", "*"},
SecondOptional | Hour | Dom | Month,
[]string{"0", "0", "5", "15", "*", "*"},
},
}
for _, test := range tests {
t.Run(test.name, func(*testing.T) {
actual, err := normalizeFields(test.input, test.options)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, test.expected) {
t.Errorf("expected %v, got %v", test.expected, actual)
}
})
}
}
func TestNormalizeFields_Errors(t *testing.T) {
tests := []struct {
name string
input []string
options ParseOption
err string
}{
{
"TwoOptionals",
[]string{"0", "5", "*", "*", "*", "*"},
SecondOptional | Minute | Hour | Dom | Month | DowOptional,
"",
},
{
"TooManyFields",
[]string{"0", "5", "*", "*"},
SecondOptional | Minute | Hour,
"",
},
{
"NoFields",
[]string{},
SecondOptional | Minute | Hour,
"",
},
{
"TooFewFields",
[]string{"*"},
SecondOptional | Minute | Hour,
"",
},
}
for _, test := range tests {
t.Run(test.name, func(*testing.T) {
actual, err := normalizeFields(test.input, test.options)
if err == nil {
t.Errorf("expected an error, got none. results: %v", actual)
}
if !strings.Contains(err.Error(), test.err) {
t.Errorf("expected error %q, got %q", test.err, err.Error())
}
})
}
}
func TestStandardSpecSchedule(t *testing.T) {
entries := []struct {
expr string
expected Schedule
err string
}{
{
expr: "5 * * * *",
expected: &SpecSchedule{1 << seconds.min, 1 << 5, all(hours), all(dom), all(months), all(dow), time.Local},
},
{
expr: "@every 5m",
expected: ConstantDelaySchedule{time.Duration(5) * time.Minute},
},
{
expr: "5 j * * *",
err: `failed to parse number: strconv.Atoi: parsing "j": invalid syntax`,
},
{
expr: "* * * *",
err: "incorrect number of fields",
},
}
for _, c := range entries {
actual, err := ParseStandard(c.expr)
if len(c.err) != 0 && (err == nil || !strings.Contains(err.Error(), c.err)) {
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
}
if len(c.err) == 0 && err != nil {
t.Errorf("%s => unexpected error %v", c.expr, err)
}
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
}
}
}
func TestNoDescriptorParser(t *testing.T) {
parser := NewParser(Minute | Hour)
_, err := parser.Parse("@every 1m")
if err == nil {
t.Error("expected an error, got none")
}
}
func every5min(loc *time.Location) *SpecSchedule {
return &SpecSchedule{1 << 0, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
}
func every5min5s(loc *time.Location) *SpecSchedule {
return &SpecSchedule{1 << 5, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
}
func midnight(loc *time.Location) *SpecSchedule {
return &SpecSchedule{1, 1, 1, all(dom), all(months), all(dow), loc}
}
func annual(loc *time.Location) *SpecSchedule {
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: 1 << months.min,
Dow: all(dow),
Location: loc,
}
}
+188
View File
@@ -0,0 +1,188 @@
package cron
import "time"
// SpecSchedule specifies a duty cycle (to the second granularity), based on a
// traditional crontab specification. It is computed initially and stored as bit sets.
type SpecSchedule struct {
Second, Minute, Hour, Dom, Month, Dow uint64
// Override location for this schedule.
Location *time.Location
}
// bounds provides a range of acceptable values (plus a map of name to value).
type bounds struct {
min, max uint
names map[string]uint
}
// The bounds for each field.
var (
seconds = bounds{0, 59, nil}
minutes = bounds{0, 59, nil}
hours = bounds{0, 23, nil}
dom = bounds{1, 31, nil}
months = bounds{1, 12, map[string]uint{
"jan": 1,
"feb": 2,
"mar": 3,
"apr": 4,
"may": 5,
"jun": 6,
"jul": 7,
"aug": 8,
"sep": 9,
"oct": 10,
"nov": 11,
"dec": 12,
}}
dow = bounds{0, 6, map[string]uint{
"sun": 0,
"mon": 1,
"tue": 2,
"wed": 3,
"thu": 4,
"fri": 5,
"sat": 6,
}}
)
const (
// Set the top bit if a star was included in the expression.
starBit = 1 << 63
)
// Next returns the next time this schedule is activated, greater than the given
// time. If no time can be found to satisfy the schedule, return the zero time.
func (s *SpecSchedule) Next(t time.Time) time.Time {
// General approach
//
// For Month, Day, Hour, Minute, Second:
// Check if the time value matches. If yes, continue to the next field.
// If the field doesn't match the schedule, then increment the field until it matches.
// While incrementing the field, a wrap-around brings it back to the beginning
// of the field list (since it is necessary to re-verify previous field
// values)
// Convert the given time into the schedule's timezone, if one is specified.
// Save the original timezone so we can convert back after we find a time.
// Note that schedules without a time zone specified (time.Local) are treated
// as local to the time provided.
origLocation := t.Location()
loc := s.Location
if loc == time.Local {
loc = t.Location()
}
if s.Location != time.Local {
t = t.In(s.Location)
}
// Start at the earliest possible time (the upcoming second).
t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
// This flag indicates whether a field has been incremented.
added := false
// If no time is found within five years, return zero.
yearLimit := t.Year() + 5
WRAP:
if t.Year() > yearLimit {
return time.Time{}
}
// Find the first applicable month.
// If it's this month, then do nothing.
for 1<<uint(t.Month())&s.Month == 0 {
// If we have to add a month, reset the other parts to 0.
if !added {
added = true
// Otherwise, set the date at the beginning (since the current time is irrelevant).
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc)
}
t = t.AddDate(0, 1, 0)
// Wrapped around.
if t.Month() == time.January {
goto WRAP
}
}
// Now get a day in that month.
//
// NOTE: This causes issues for daylight savings regimes where midnight does
// not exist. For example: Sao Paulo has DST that transforms midnight on
// 11/3 into 1am. Handle that by noticing when the Hour ends up != 0.
for !dayMatches(s, t) {
if !added {
added = true
t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc)
}
t = t.AddDate(0, 0, 1)
// Notice if the hour is no longer midnight due to DST.
// Add an hour if it's 23, subtract an hour if it's 1.
if t.Hour() != 0 {
if t.Hour() > 12 {
t = t.Add(time.Duration(24-t.Hour()) * time.Hour)
} else {
t = t.Add(time.Duration(-t.Hour()) * time.Hour)
}
}
if t.Day() == 1 {
goto WRAP
}
}
for 1<<uint(t.Hour())&s.Hour == 0 {
if !added {
added = true
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, loc)
}
t = t.Add(1 * time.Hour)
if t.Hour() == 0 {
goto WRAP
}
}
for 1<<uint(t.Minute())&s.Minute == 0 {
if !added {
added = true
t = t.Truncate(time.Minute)
}
t = t.Add(1 * time.Minute)
if t.Minute() == 0 {
goto WRAP
}
}
for 1<<uint(t.Second())&s.Second == 0 {
if !added {
added = true
t = t.Truncate(time.Second)
}
t = t.Add(1 * time.Second)
if t.Second() == 0 {
goto WRAP
}
}
return t.In(origLocation)
}
// dayMatches returns true if the schedule's day-of-week and day-of-month
// restrictions are satisfied by the given time.
func dayMatches(s *SpecSchedule, t time.Time) bool {
var (
domMatch = 1<<uint(t.Day())&s.Dom > 0
dowMatch = 1<<uint(t.Weekday())&s.Dow > 0
)
if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
return domMatch && dowMatch
}
return domMatch || dowMatch
}
+301
View File
@@ -0,0 +1,301 @@
//nolint:all
package cron
import (
"strings"
"testing"
"time"
)
func TestActivation(t *testing.T) {
tests := []struct {
time, spec string
expected bool
}{
// Every fifteen minutes.
{"Mon Jul 9 15:00 2012", "0/15 * * * *", true},
{"Mon Jul 9 15:45 2012", "0/15 * * * *", true},
{"Mon Jul 9 15:40 2012", "0/15 * * * *", false},
// Every fifteen minutes, starting at 5 minutes.
{"Mon Jul 9 15:05 2012", "5/15 * * * *", true},
{"Mon Jul 9 15:20 2012", "5/15 * * * *", true},
{"Mon Jul 9 15:50 2012", "5/15 * * * *", true},
// Named months
{"Sun Jul 15 15:00 2012", "0/15 * * Jul *", true},
{"Sun Jul 15 15:00 2012", "0/15 * * Jun *", false},
// Everything set.
{"Sun Jul 15 08:30 2012", "30 08 ? Jul Sun", true},
{"Sun Jul 15 08:30 2012", "30 08 15 Jul ?", true},
{"Mon Jul 16 08:30 2012", "30 08 ? Jul Sun", false},
{"Mon Jul 16 08:30 2012", "30 08 15 Jul ?", false},
// Predefined schedules
{"Mon Jul 9 15:00 2012", "@hourly", true},
{"Mon Jul 9 15:04 2012", "@hourly", false},
{"Mon Jul 9 15:00 2012", "@daily", false},
{"Mon Jul 9 00:00 2012", "@daily", true},
{"Mon Jul 9 00:00 2012", "@weekly", false},
{"Sun Jul 8 00:00 2012", "@weekly", true},
{"Sun Jul 8 01:00 2012", "@weekly", false},
{"Sun Jul 8 00:00 2012", "@monthly", false},
{"Sun Jul 1 00:00 2012", "@monthly", true},
// Test interaction of DOW and DOM.
// If both are restricted, then only one needs to match.
{"Sun Jul 15 00:00 2012", "* * 1,15 * Sun", true},
{"Fri Jun 15 00:00 2012", "* * 1,15 * Sun", true},
{"Wed Aug 1 00:00 2012", "* * 1,15 * Sun", true},
{"Sun Jul 15 00:00 2012", "* * */10 * Sun", true}, // verifies #70
// However, if one has a star, then both need to match.
{"Sun Jul 15 00:00 2012", "* * * * Mon", false},
{"Mon Jul 9 00:00 2012", "* * 1,15 * *", false},
{"Sun Jul 15 00:00 2012", "* * 1,15 * *", true},
{"Sun Jul 15 00:00 2012", "* * */2 * Sun", true},
}
for _, test := range tests {
sched, err := ParseStandard(test.spec)
if err != nil {
t.Error(err)
continue
}
actual := sched.Next(getTime(test.time).Add(-1 * time.Second))
expected := getTime(test.time)
if test.expected && expected != actual || !test.expected && expected == actual {
t.Errorf("Fail evaluating %s on %s: (expected) %s != %s (actual)",
test.spec, test.time, expected, actual)
}
}
}
func TestNext(t *testing.T) {
runs := []struct {
time, spec string
expected string
}{
// Simple cases
{"Mon Jul 9 14:45 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
{"Mon Jul 9 14:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
{"Mon Jul 9 14:59:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
// Wrap around hours
{"Mon Jul 9 15:45 2012", "0 20-35/15 * * * *", "Mon Jul 9 16:20 2012"},
// Wrap around days
{"Mon Jul 9 23:46 2012", "0 */15 * * * *", "Tue Jul 10 00:00 2012"},
{"Mon Jul 9 23:45 2012", "0 20-35/15 * * * *", "Tue Jul 10 00:20 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * * * *", "Tue Jul 10 00:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 * * *", "Tue Jul 10 01:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 10-12 * * *", "Tue Jul 10 10:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 */2 * *", "Thu Jul 11 01:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 * *", "Wed Jul 10 00:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 Jul *", "Wed Jul 10 00:20:15 2012"},
// Wrap around months
{"Mon Jul 9 23:35 2012", "0 0 0 9 Apr-Oct ?", "Thu Aug 9 00:00 2012"},
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Apr,Aug,Oct Mon", "Tue Aug 1 00:00 2012"},
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Oct Mon", "Mon Oct 1 00:00 2012"},
// Wrap around years
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon", "Mon Feb 4 00:00 2013"},
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon/2", "Fri Feb 1 00:00 2013"},
// Wrap around minute, hour, day, month, and year
{"Mon Dec 31 23:59:45 2012", "0 * * * * *", "Tue Jan 1 00:00:00 2013"},
// Leap year
{"Mon Jul 9 23:35 2012", "0 0 0 29 Feb ?", "Mon Feb 29 00:00 2016"},
// Daylight savings time 2am EST (-5) -> 3am EDT (-4)
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 30 2 11 Mar ?", "2013-03-11T02:30:00-0400"},
// hourly job
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T01:00:00-0500"},
{"2012-03-11T01:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T03:00:00-0400"},
{"2012-03-11T03:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T04:00:00-0400"},
{"2012-03-11T04:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T05:00:00-0400"},
// hourly job using CRON_TZ
{"2012-03-11T00:00:00-0500", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T01:00:00-0500"},
{"2012-03-11T01:00:00-0500", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T03:00:00-0400"},
{"2012-03-11T03:00:00-0400", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T04:00:00-0400"},
{"2012-03-11T04:00:00-0400", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T05:00:00-0400"},
// 1am nightly job
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-03-11T01:00:00-0500"},
{"2012-03-11T01:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-03-12T01:00:00-0400"},
// 2am nightly job (skipped)
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 2 * * ?", "2012-03-12T02:00:00-0400"},
// Daylight savings time 2am EDT (-4) => 1am EST (-5)
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 30 2 04 Nov ?", "2012-11-04T02:30:00-0500"},
{"2012-11-04T01:45:00-0400", "TZ=America/New_York 0 30 1 04 Nov ?", "2012-11-04T01:30:00-0500"},
// hourly job
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T01:00:00-0400"},
{"2012-11-04T01:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T01:00:00-0500"},
{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T02:00:00-0500"},
// 1am nightly job (runs twice)
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 1 * * ?", "2012-11-04T01:00:00-0400"},
{"2012-11-04T01:00:00-0400", "TZ=America/New_York 0 0 1 * * ?", "2012-11-04T01:00:00-0500"},
{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-11-05T01:00:00-0500"},
// 2am nightly job
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 2 * * ?", "2012-11-04T02:00:00-0500"},
{"2012-11-04T02:00:00-0500", "TZ=America/New_York 0 0 2 * * ?", "2012-11-05T02:00:00-0500"},
// 3am nightly job
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 3 * * ?", "2012-11-04T03:00:00-0500"},
{"2012-11-04T03:00:00-0500", "TZ=America/New_York 0 0 3 * * ?", "2012-11-05T03:00:00-0500"},
// hourly job
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 * * * ?", "2012-11-04T01:00:00-0400"},
{"TZ=America/New_York 2012-11-04T01:00:00-0400", "0 0 * * * ?", "2012-11-04T01:00:00-0500"},
{"TZ=America/New_York 2012-11-04T01:00:00-0500", "0 0 * * * ?", "2012-11-04T02:00:00-0500"},
// 1am nightly job (runs twice)
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 1 * * ?", "2012-11-04T01:00:00-0400"},
{"TZ=America/New_York 2012-11-04T01:00:00-0400", "0 0 1 * * ?", "2012-11-04T01:00:00-0500"},
{"TZ=America/New_York 2012-11-04T01:00:00-0500", "0 0 1 * * ?", "2012-11-05T01:00:00-0500"},
// 2am nightly job
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 2 * * ?", "2012-11-04T02:00:00-0500"},
{"TZ=America/New_York 2012-11-04T02:00:00-0500", "0 0 2 * * ?", "2012-11-05T02:00:00-0500"},
// 3am nightly job
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 3 * * ?", "2012-11-04T03:00:00-0500"},
{"TZ=America/New_York 2012-11-04T03:00:00-0500", "0 0 3 * * ?", "2012-11-05T03:00:00-0500"},
// Unsatisfiable
{"Mon Jul 9 23:35 2012", "0 0 0 30 Feb ?", ""},
{"Mon Jul 9 23:35 2012", "0 0 0 31 Apr ?", ""},
// Monthly job
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 3 3 * ?", "2012-12-03T03:00:00-0500"},
// Test the scenario of DST resulting in midnight not being a valid time.
// https://github.com/robfig/cron/issues/157
{"2018-10-17T05:00:00-0400", "TZ=America/Sao_Paulo 0 0 9 10 * ?", "2018-11-10T06:00:00-0500"},
{"2018-02-14T05:00:00-0500", "TZ=America/Sao_Paulo 0 0 9 22 * ?", "2018-02-22T07:00:00-0500"},
}
for _, c := range runs {
sched, err := secondParser.Parse(c.spec)
if err != nil {
t.Error(err)
continue
}
actual := sched.Next(getTime(c.time))
expected := getTime(c.expected)
if !actual.Equal(expected) {
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
}
}
}
func TestErrors(t *testing.T) {
invalidSpecs := []string{
"xyz",
"60 0 * * *",
"0 60 * * *",
"0 0 * * XYZ",
}
for _, spec := range invalidSpecs {
_, err := ParseStandard(spec)
if err == nil {
t.Error("expected an error parsing: ", spec)
}
}
}
func getTime(value string) time.Time {
if value == "" {
return time.Time{}
}
var location = time.Local
if strings.HasPrefix(value, "TZ=") {
parts := strings.Fields(value)
loc, err := time.LoadLocation(parts[0][len("TZ="):])
if err != nil {
panic("could not parse location:" + err.Error())
}
location = loc
value = parts[1]
}
var layouts = []string{
"Mon Jan 2 15:04 2006",
"Mon Jan 2 15:04:05 2006",
}
for _, layout := range layouts {
if t, err := time.ParseInLocation(layout, value, location); err == nil {
return t
}
}
if t, err := time.ParseInLocation("2006-01-02T15:04:05-0700", value, location); err == nil {
return t
}
panic("could not parse time value " + value)
}
func TestNextWithTz(t *testing.T) {
runs := []struct {
time, spec string
expected string
}{
// Failing tests
{"2016-01-03T13:09:03+0530", "14 14 * * *", "2016-01-03T14:14:00+0530"},
{"2016-01-03T04:09:03+0530", "14 14 * * ?", "2016-01-03T14:14:00+0530"},
// Passing tests
{"2016-01-03T14:09:03+0530", "14 14 * * *", "2016-01-03T14:14:00+0530"},
{"2016-01-03T14:00:00+0530", "14 14 * * ?", "2016-01-03T14:14:00+0530"},
}
for _, c := range runs {
sched, err := ParseStandard(c.spec)
if err != nil {
t.Error(err)
continue
}
actual := sched.Next(getTimeTZ(c.time))
expected := getTimeTZ(c.expected)
if !actual.Equal(expected) {
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
}
}
}
func getTimeTZ(value string) time.Time {
if value == "" {
return time.Time{}
}
t, err := time.Parse("Mon Jan 2 15:04 2006", value)
if err != nil {
t, err = time.Parse("Mon Jan 2 15:04:05 2006", value)
if err != nil {
t, err = time.Parse("2006-01-02T15:04:05-0700", value)
if err != nil {
panic(err)
}
}
}
return t
}
// https://github.com/robfig/cron/issues/144
func TestSlash0NoHang(t *testing.T) {
schedule := "TZ=America/New_York 15/0 * * * *"
_, err := ParseStandard(schedule)
if err == nil {
t.Error("expected an error on 0 increment")
}
}
+507
View File
@@ -0,0 +1,507 @@
# Email Plugin
SMTP email sending functionality for self-hosted Memos instances.
## Overview
This plugin provides a simple, reliable email sending interface following industry-standard SMTP protocols. It's designed for self-hosted environments where instance administrators configure their own email service, similar to platforms like GitHub, GitLab, and Discourse.
## Features
- Standard SMTP protocol support
- TLS/STARTTLS and SSL/TLS encryption
- HTML and plain text emails
- Multiple recipients (To, Cc, Bcc)
- Synchronous and asynchronous sending
- Detailed error reporting with context
- Works with all major email providers
- Reply-To header support
- RFC 5322 compliant message formatting
## Quick Start
### 1. Configure SMTP Settings
```go
import "github.com/usememos/memos/plugin/email"
config := &email.Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
SMTPUsername: "your-email@gmail.com",
SMTPPassword: "your-app-password",
FromEmail: "noreply@yourdomain.com",
FromName: "Memos",
UseTLS: true,
}
```
### 2. Create and Send Email
```go
message := &email.Message{
To: []string{"user@example.com"},
Subject: "Welcome to Memos!",
Body: "Thanks for signing up.",
IsHTML: false,
}
// Synchronous send (waits for result)
err := email.Send(config, message)
if err != nil {
log.Printf("Failed to send email: %v", err)
}
// Asynchronous send (returns immediately)
email.SendAsync(config, message)
```
## Provider Configuration
### Gmail
Requires an [App Password](https://support.google.com/accounts/answer/185833) (2FA must be enabled):
```go
config := &email.Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
SMTPUsername: "your-email@gmail.com",
SMTPPassword: "your-16-char-app-password",
FromEmail: "your-email@gmail.com",
FromName: "Memos",
UseTLS: true,
}
```
**Alternative (SSL):**
```go
config := &email.Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 465,
SMTPUsername: "your-email@gmail.com",
SMTPPassword: "your-16-char-app-password",
FromEmail: "your-email@gmail.com",
FromName: "Memos",
UseSSL: true,
}
```
### SendGrid
```go
config := &email.Config{
SMTPHost: "smtp.sendgrid.net",
SMTPPort: 587,
SMTPUsername: "apikey",
SMTPPassword: "your-sendgrid-api-key",
FromEmail: "noreply@yourdomain.com",
FromName: "Memos",
UseTLS: true,
}
```
### AWS SES
```go
config := &email.Config{
SMTPHost: "email-smtp.us-east-1.amazonaws.com",
SMTPPort: 587,
SMTPUsername: "your-smtp-username",
SMTPPassword: "your-smtp-password",
FromEmail: "verified@yourdomain.com",
FromName: "Memos",
UseTLS: true,
}
```
**Note:** Replace `us-east-1` with your AWS region. Email must be verified in SES.
### Mailgun
```go
config := &email.Config{
SMTPHost: "smtp.mailgun.org",
SMTPPort: 587,
SMTPUsername: "postmaster@yourdomain.com",
SMTPPassword: "your-mailgun-smtp-password",
FromEmail: "noreply@yourdomain.com",
FromName: "Memos",
UseTLS: true,
}
```
### Self-Hosted SMTP (Postfix, Exim, etc.)
```go
config := &email.Config{
SMTPHost: "mail.yourdomain.com",
SMTPPort: 587,
SMTPUsername: "username",
SMTPPassword: "password",
FromEmail: "noreply@yourdomain.com",
FromName: "Memos",
UseTLS: true,
}
```
## HTML Emails
```go
message := &email.Message{
To: []string{"user@example.com"},
Subject: "Welcome to Memos!",
Body: `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body style="font-family: Arial, sans-serif;">
<h1 style="color: #333;">Welcome to Memos!</h1>
<p>We're excited to have you on board.</p>
<a href="https://yourdomain.com" style="background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Get Started</a>
</body>
</html>
`,
IsHTML: true,
}
email.Send(config, message)
```
## Multiple Recipients
```go
message := &email.Message{
To: []string{"user1@example.com", "user2@example.com"},
Cc: []string{"manager@example.com"},
Bcc: []string{"admin@example.com"},
Subject: "Team Update",
Body: "Important team announcement...",
ReplyTo: "support@yourdomain.com",
}
email.Send(config, message)
```
## Testing
### Run Tests
```bash
# All tests
go test ./plugin/email/... -v
# With coverage
go test ./plugin/email/... -v -cover
# With race detector
go test ./plugin/email/... -race
```
### Manual Testing
Create a simple test program:
```go
package main
import (
"log"
"github.com/usememos/memos/plugin/email"
)
func main() {
config := &email.Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
SMTPUsername: "your-email@gmail.com",
SMTPPassword: "your-app-password",
FromEmail: "your-email@gmail.com",
FromName: "Test",
UseTLS: true,
}
message := &email.Message{
To: []string{"recipient@example.com"},
Subject: "Test Email",
Body: "This is a test email from Memos email plugin.",
}
if err := email.Send(config, message); err != nil {
log.Fatalf("Failed to send email: %v", err)
}
log.Println("Email sent successfully!")
}
```
## Security Best Practices
### 1. Use TLS/SSL Encryption
Always enable encryption in production:
```go
// STARTTLS (port 587) - Recommended
config.UseTLS = true
// SSL/TLS (port 465)
config.UseSSL = true
```
### 2. Secure Credential Storage
Never hardcode credentials. Use environment variables:
```go
import "os"
config := &email.Config{
SMTPHost: os.Getenv("SMTP_HOST"),
SMTPPort: 587,
SMTPUsername: os.Getenv("SMTP_USERNAME"),
SMTPPassword: os.Getenv("SMTP_PASSWORD"),
FromEmail: os.Getenv("SMTP_FROM_EMAIL"),
UseTLS: true,
}
```
### 3. Use App-Specific Passwords
For Gmail and similar services, use app passwords instead of your main account password.
### 4. Validate and Sanitize Input
Always validate email addresses and sanitize content:
```go
// Validate before sending
if err := message.Validate(); err != nil {
return err
}
```
### 5. Implement Rate Limiting
Prevent abuse by limiting email sending:
```go
// Example using golang.org/x/time/rate
limiter := rate.NewLimiter(rate.Every(time.Second), 10) // 10 emails per second
if !limiter.Allow() {
return errors.New("rate limit exceeded")
}
```
### 6. Monitor and Log
Log email sending activity for security monitoring:
```go
if err := email.Send(config, message); err != nil {
slog.Error("Email send failed",
slog.String("recipient", message.To[0]),
slog.Any("error", err))
}
```
## Common Ports
| Port | Protocol | Security | Use Case |
|------|----------|----------|----------|
| **587** | SMTP + STARTTLS | Encrypted | **Recommended** for most providers |
| **465** | SMTP over SSL/TLS | Encrypted | Alternative secure option |
| **25** | SMTP | Unencrypted | Legacy, often blocked by ISPs |
| **2525** | SMTP + STARTTLS | Encrypted | Alternative when 587 is blocked |
**Port 587 (STARTTLS)** is the recommended standard for modern SMTP:
```go
config := &email.Config{
SMTPPort: 587,
UseTLS: true,
}
```
**Port 465 (SSL/TLS)** is the alternative:
```go
config := &email.Config{
SMTPPort: 465,
UseSSL: true,
}
```
## Error Handling
The package provides detailed, contextual errors:
```go
err := email.Send(config, message)
if err != nil {
// Error messages include context:
switch {
case strings.Contains(err.Error(), "invalid email configuration"):
// Configuration error (missing host, invalid port, etc.)
log.Printf("Configuration error: %v", err)
case strings.Contains(err.Error(), "invalid email message"):
// Message validation error (missing recipients, subject, body)
log.Printf("Message error: %v", err)
case strings.Contains(err.Error(), "authentication failed"):
// SMTP authentication failed (wrong credentials)
log.Printf("Auth error: %v", err)
case strings.Contains(err.Error(), "failed to connect"):
// Network/connection error
log.Printf("Connection error: %v", err)
case strings.Contains(err.Error(), "recipient rejected"):
// SMTP server rejected recipient
log.Printf("Recipient error: %v", err)
default:
log.Printf("Unknown error: %v", err)
}
}
```
### Common Error Messages
```
❌ "invalid email configuration: SMTP host is required"
→ Fix: Set config.SMTPHost
❌ "invalid email configuration: SMTP port must be between 1 and 65535"
→ Fix: Set valid config.SMTPPort (usually 587 or 465)
❌ "invalid email configuration: from email is required"
→ Fix: Set config.FromEmail
❌ "invalid email message: at least one recipient is required"
→ Fix: Set message.To with at least one email address
❌ "invalid email message: subject is required"
→ Fix: Set message.Subject
❌ "invalid email message: body is required"
→ Fix: Set message.Body
❌ "SMTP authentication failed"
→ Fix: Check credentials (username/password)
❌ "failed to connect to SMTP server"
→ Fix: Verify host/port, check firewall, ensure TLS/SSL settings match server
```
### Async Error Handling
For async sending, errors are logged automatically:
```go
email.SendAsync(config, message)
// Errors logged as:
// [WARN] Failed to send email asynchronously recipients=user@example.com error=...
```
## Dependencies
### Required
- **Go 1.25+**
- Standard library: `net/smtp`, `crypto/tls`
- `github.com/pkg/errors` - Error wrapping with context
### No External SMTP Libraries
This plugin uses Go's standard `net/smtp` library for maximum compatibility and minimal dependencies.
## API Reference
### Types
#### `Config`
```go
type Config struct {
SMTPHost string // SMTP server hostname
SMTPPort int // SMTP server port
SMTPUsername string // SMTP auth username
SMTPPassword string // SMTP auth password
FromEmail string // From email address
FromName string // From display name (optional)
UseTLS bool // Enable STARTTLS (port 587)
UseSSL bool // Enable SSL/TLS (port 465)
}
```
#### `Message`
```go
type Message struct {
To []string // Recipients
Cc []string // CC recipients (optional)
Bcc []string // BCC recipients (optional)
Subject string // Email subject
Body string // Email body (plain text or HTML)
IsHTML bool // true for HTML, false for plain text
ReplyTo string // Reply-To address (optional)
}
```
### Functions
#### `Send(config *Config, message *Message) error`
Sends an email synchronously. Blocks until email is sent or error occurs.
#### `SendAsync(config *Config, message *Message)`
Sends an email asynchronously in a goroutine. Returns immediately. Errors are logged.
#### `NewClient(config *Config) *Client`
Creates a new SMTP client for advanced usage.
#### `Client.Send(message *Message) error`
Sends email using the client's configuration.
## Architecture
```
plugin/email/
├── config.go # SMTP configuration types
├── message.go # Email message types and formatting
├── client.go # SMTP client implementation
├── email.go # High-level Send/SendAsync API
├── doc.go # Package documentation
└── *_test.go # Unit tests
```
## License
Part of the Memos project. See main repository for license details.
## Contributing
This plugin follows the Memos contribution guidelines. Please ensure:
1. All code is tested (TDD approach)
2. Tests pass: `go test ./plugin/email/... -v`
3. Code is formatted: `go fmt ./plugin/email/...`
4. No linting errors: `golangci-lint run ./plugin/email/...`
## Support
For issues and questions:
- Memos GitHub Issues: https://github.com/usememos/memos/issues
- Memos Documentation: https://usememos.com/docs
## Roadmap
Future enhancements may include:
- Email template system
- Attachment support
- Inline image embedding
- Email queuing system
- Delivery status tracking
- Bounce handling
+143
View File
@@ -0,0 +1,143 @@
package email
import (
"crypto/tls"
"net/smtp"
"github.com/pkg/errors"
)
// Client represents an SMTP email client.
type Client struct {
config *Config
}
// NewClient creates a new email client with the given configuration.
func NewClient(config *Config) *Client {
return &Client{
config: config,
}
}
// validateConfig validates the client configuration.
func (c *Client) validateConfig() error {
if c.config == nil {
return errors.New("email configuration is required")
}
return c.config.Validate()
}
// createAuth creates an SMTP auth mechanism if credentials are provided.
func (c *Client) createAuth() smtp.Auth {
if c.config.SMTPUsername == "" && c.config.SMTPPassword == "" {
return nil
}
return smtp.PlainAuth("", c.config.SMTPUsername, c.config.SMTPPassword, c.config.SMTPHost)
}
// createTLSConfig creates a TLS configuration for secure connections.
func (c *Client) createTLSConfig() *tls.Config {
return &tls.Config{
ServerName: c.config.SMTPHost,
MinVersion: tls.VersionTLS12,
}
}
// Send sends an email message via SMTP.
func (c *Client) Send(message *Message) error {
// Validate configuration
if err := c.validateConfig(); err != nil {
return errors.Wrap(err, "invalid email configuration")
}
// Validate message
if message == nil {
return errors.New("message is required")
}
if err := message.Validate(); err != nil {
return errors.Wrap(err, "invalid email message")
}
// Format the message
body := message.Format(c.config.FromEmail, c.config.FromName)
// Get all recipients
recipients := message.GetAllRecipients()
// Create auth
auth := c.createAuth()
// Send based on encryption type
if c.config.UseSSL {
return c.sendWithSSL(auth, recipients, body)
}
return c.sendWithTLS(auth, recipients, body)
}
// sendWithTLS sends email using STARTTLS (port 587).
func (c *Client) sendWithTLS(auth smtp.Auth, recipients []string, body string) error {
serverAddr := c.config.GetServerAddress()
if c.config.UseTLS {
// Use STARTTLS
return smtp.SendMail(serverAddr, auth, c.config.FromEmail, recipients, []byte(body))
}
// Send without encryption (not recommended)
return smtp.SendMail(serverAddr, auth, c.config.FromEmail, recipients, []byte(body))
}
// sendWithSSL sends email using SSL/TLS (port 465).
func (c *Client) sendWithSSL(auth smtp.Auth, recipients []string, body string) error {
serverAddr := c.config.GetServerAddress()
// Create TLS connection
tlsConfig := c.createTLSConfig()
conn, err := tls.Dial("tcp", serverAddr, tlsConfig)
if err != nil {
return errors.Wrapf(err, "failed to connect to SMTP server with SSL: %s", serverAddr)
}
defer conn.Close()
// Create SMTP client
client, err := smtp.NewClient(conn, c.config.SMTPHost)
if err != nil {
return errors.Wrap(err, "failed to create SMTP client")
}
defer client.Quit()
// Authenticate
if auth != nil {
if err := client.Auth(auth); err != nil {
return errors.Wrap(err, "SMTP authentication failed")
}
}
// Set sender
if err := client.Mail(c.config.FromEmail); err != nil {
return errors.Wrap(err, "failed to set sender")
}
// Set recipients
for _, recipient := range recipients {
if err := client.Rcpt(recipient); err != nil {
return errors.Wrapf(err, "failed to set recipient: %s", recipient)
}
}
// Send message body
writer, err := client.Data()
if err != nil {
return errors.Wrap(err, "failed to send DATA command")
}
if _, err := writer.Write([]byte(body)); err != nil {
return errors.Wrap(err, "failed to write message body")
}
if err := writer.Close(); err != nil {
return errors.Wrap(err, "failed to close message writer")
}
return nil
}
+121
View File
@@ -0,0 +1,121 @@
package email
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewClient(t *testing.T) {
config := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
SMTPUsername: "user@example.com",
SMTPPassword: "password",
FromEmail: "noreply@example.com",
FromName: "Test App",
UseTLS: true,
}
client := NewClient(config)
assert.NotNil(t, client)
assert.Equal(t, config, client.config)
}
func TestClientValidateConfig(t *testing.T) {
tests := []struct {
name string
config *Config
wantErr bool
}{
{
name: "valid config",
config: &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
FromEmail: "test@example.com",
},
wantErr: false,
},
{
name: "nil config",
config: nil,
wantErr: true,
},
{
name: "invalid config",
config: &Config{
SMTPHost: "",
SMTPPort: 587,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := NewClient(tt.config)
err := client.validateConfig()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestClientSendValidation(t *testing.T) {
config := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
FromEmail: "test@example.com",
}
client := NewClient(config)
tests := []struct {
name string
message *Message
wantErr bool
}{
{
name: "valid message",
message: &Message{
To: []string{"recipient@example.com"},
Subject: "Test",
Body: "Test body",
},
wantErr: false, // Will fail on actual send, but passes validation
},
{
name: "nil message",
message: nil,
wantErr: true,
},
{
name: "invalid message",
message: &Message{
To: []string{},
Subject: "Test",
Body: "Test",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := client.Send(tt.message)
// We expect validation errors for invalid messages
// For valid messages, we'll get connection errors (which is expected in tests)
if tt.wantErr {
assert.Error(t, err)
// Should fail validation before attempting connection
assert.NotContains(t, err.Error(), "dial")
}
// Note: We don't assert NoError for valid messages because
// we don't have a real SMTP server in tests
})
}
}
+47
View File
@@ -0,0 +1,47 @@
package email
import (
"fmt"
"github.com/pkg/errors"
)
// Config represents the SMTP configuration for email sending.
// These settings should be provided by the self-hosted instance administrator.
type Config struct {
// SMTPHost is the SMTP server hostname (e.g., "smtp.gmail.com")
SMTPHost string
// SMTPPort is the SMTP server port (common: 587 for TLS, 465 for SSL, 25 for unencrypted)
SMTPPort int
// SMTPUsername is the SMTP authentication username (usually the email address)
SMTPUsername string
// SMTPPassword is the SMTP authentication password or app-specific password
SMTPPassword string
// FromEmail is the email address that will appear in the "From" field
FromEmail string
// FromName is the display name that will appear in the "From" field
FromName string
// UseTLS enables STARTTLS encryption (recommended for port 587)
UseTLS bool
// UseSSL enables SSL/TLS encryption (for port 465)
UseSSL bool
}
// Validate checks if the configuration is valid.
func (c *Config) Validate() error {
if c.SMTPHost == "" {
return errors.New("SMTP host is required")
}
if c.SMTPPort <= 0 || c.SMTPPort > 65535 {
return errors.New("SMTP port must be between 1 and 65535")
}
if c.FromEmail == "" {
return errors.New("from email is required")
}
return nil
}
// GetServerAddress returns the SMTP server address in the format "host:port".
func (c *Config) GetServerAddress() string {
return fmt.Sprintf("%s:%d", c.SMTPHost, c.SMTPPort)
}
+80
View File
@@ -0,0 +1,80 @@
package email
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConfigValidation(t *testing.T) {
tests := []struct {
name string
config *Config
wantErr bool
}{
{
name: "valid config",
config: &Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
SMTPUsername: "user@example.com",
SMTPPassword: "password",
FromEmail: "noreply@example.com",
FromName: "Memos",
},
wantErr: false,
},
{
name: "missing host",
config: &Config{
SMTPPort: 587,
SMTPUsername: "user@example.com",
SMTPPassword: "password",
FromEmail: "noreply@example.com",
},
wantErr: true,
},
{
name: "invalid port",
config: &Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 0,
SMTPUsername: "user@example.com",
SMTPPassword: "password",
FromEmail: "noreply@example.com",
},
wantErr: true,
},
{
name: "missing from email",
config: &Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
SMTPUsername: "user@example.com",
SMTPPassword: "password",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.config.Validate()
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestConfigGetServerAddress(t *testing.T) {
config := &Config{
SMTPHost: "smtp.gmail.com",
SMTPPort: 587,
}
expected := "smtp.gmail.com:587"
assert.Equal(t, expected, config.GetServerAddress())
}
+98
View File
@@ -0,0 +1,98 @@
// Package email provides SMTP email sending functionality for self-hosted Memos instances.
//
// This package is designed for self-hosted environments where instance administrators
// configure their own SMTP servers. It follows industry-standard patterns used by
// platforms like GitHub, GitLab, and Discourse.
//
// # Configuration
//
// The package requires SMTP server configuration provided by the instance administrator:
//
// config := &email.Config{
// SMTPHost: "smtp.gmail.com",
// SMTPPort: 587,
// SMTPUsername: "your-email@gmail.com",
// SMTPPassword: "your-app-password",
// FromEmail: "noreply@yourdomain.com",
// FromName: "Memos Notifications",
// UseTLS: true,
// }
//
// # Common SMTP Settings
//
// Gmail (requires App Password):
// - Host: smtp.gmail.com
// - Port: 587 (TLS) or 465 (SSL)
// - Username: your-email@gmail.com
// - UseTLS: true (for port 587) or UseSSL: true (for port 465)
//
// SendGrid:
// - Host: smtp.sendgrid.net
// - Port: 587
// - Username: apikey
// - Password: your-sendgrid-api-key
// - UseTLS: true
//
// AWS SES:
// - Host: email-smtp.[region].amazonaws.com
// - Port: 587
// - Username: your-smtp-username
// - Password: your-smtp-password
// - UseTLS: true
//
// Mailgun:
// - Host: smtp.mailgun.org
// - Port: 587
// - Username: your-mailgun-smtp-username
// - Password: your-mailgun-smtp-password
// - UseTLS: true
//
// # Sending Email
//
// Synchronous (waits for completion):
//
// message := &email.Message{
// To: []string{"user@example.com"},
// Subject: "Welcome to Memos",
// Body: "Thank you for joining!",
// IsHTML: false,
// }
//
// err := email.Send(config, message)
// if err != nil {
// // Handle error
// }
//
// Asynchronous (returns immediately):
//
// email.SendAsync(config, message)
// // Errors are logged but not returned
//
// # HTML Email
//
// message := &email.Message{
// To: []string{"user@example.com"},
// Subject: "Welcome!",
// Body: "<html><body><h1>Welcome to Memos!</h1></body></html>",
// IsHTML: true,
// }
//
// # Security Considerations
//
// - Always use TLS (port 587) or SSL (port 465) for production
// - Store SMTP credentials securely (environment variables or secrets management)
// - Use app-specific passwords for services like Gmail
// - Validate and sanitize email content to prevent injection attacks
// - Rate limit email sending to prevent abuse
//
// # Error Handling
//
// The package returns descriptive errors for common issues:
// - Configuration validation errors (missing host, invalid port, etc.)
// - Message validation errors (missing recipients, subject, or body)
// - Connection errors (cannot reach SMTP server)
// - Authentication errors (invalid credentials)
// - SMTP protocol errors (recipient rejected, etc.)
//
// All errors are wrapped with context using github.com/pkg/errors for better debugging.
package email
+43
View File
@@ -0,0 +1,43 @@
package email
import (
"log/slog"
"github.com/pkg/errors"
)
// Send sends an email synchronously.
// Returns an error if the email fails to send.
func Send(config *Config, message *Message) error {
if config == nil {
return errors.New("email configuration is required")
}
if message == nil {
return errors.New("email message is required")
}
client := NewClient(config)
return client.Send(message)
}
// SendAsync sends an email asynchronously.
// It spawns a new goroutine to handle the sending and does not wait for the response.
// Any errors are logged but not returned.
func SendAsync(config *Config, message *Message) {
go func() {
if err := Send(config, message); err != nil {
// Since we're in a goroutine, we can only log the error
recipients := ""
if message != nil && len(message.To) > 0 {
recipients = message.To[0]
if len(message.To) > 1 {
recipients += " and others"
}
}
slog.Warn("Failed to send email asynchronously",
slog.String("recipients", recipients),
slog.Any("error", err))
}
}()
}
+127
View File
@@ -0,0 +1,127 @@
package email
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"golang.org/x/sync/errgroup"
)
func TestSend(t *testing.T) {
config := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
FromEmail: "test@example.com",
}
message := &Message{
To: []string{"recipient@example.com"},
Subject: "Test",
Body: "Test body",
}
// This will fail to connect (no real server), but should validate inputs
err := Send(config, message)
// We expect an error because there's no real SMTP server
// But it should be a connection error, not a validation error
assert.Error(t, err)
assert.Contains(t, err.Error(), "dial")
}
func TestSendValidation(t *testing.T) {
tests := []struct {
name string
config *Config
message *Message
wantErr bool
errMsg string
}{
{
name: "nil config",
config: nil,
message: &Message{To: []string{"test@example.com"}, Subject: "Test", Body: "Test"},
wantErr: true,
errMsg: "configuration is required",
},
{
name: "nil message",
config: &Config{SMTPHost: "smtp.example.com", SMTPPort: 587, FromEmail: "from@example.com"},
message: nil,
wantErr: true,
errMsg: "message is required",
},
{
name: "invalid config",
config: &Config{
SMTPHost: "",
SMTPPort: 587,
},
message: &Message{To: []string{"test@example.com"}, Subject: "Test", Body: "Test"},
wantErr: true,
errMsg: "invalid email configuration",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Send(tt.config, tt.message)
if tt.wantErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.errMsg)
}
})
}
}
func TestSendAsync(t *testing.T) {
config := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
FromEmail: "test@example.com",
}
message := &Message{
To: []string{"recipient@example.com"},
Subject: "Test Async",
Body: "Test async body",
}
// SendAsync should not block
start := time.Now()
SendAsync(config, message)
duration := time.Since(start)
// Should return almost immediately (< 100ms)
assert.Less(t, duration, 100*time.Millisecond)
// Give goroutine time to start
time.Sleep(50 * time.Millisecond)
}
func TestSendAsyncConcurrent(t *testing.T) {
config := &Config{
SMTPHost: "smtp.example.com",
SMTPPort: 587,
FromEmail: "test@example.com",
}
g := errgroup.Group{}
count := 5
for i := 0; i < count; i++ {
g.Go(func() error {
message := &Message{
To: []string{"recipient@example.com"},
Subject: "Concurrent Test",
Body: "Test body",
}
SendAsync(config, message)
return nil
})
}
if err := g.Wait(); err != nil {
t.Fatalf("SendAsync calls failed: %v", err)
}
}
+91
View File
@@ -0,0 +1,91 @@
package email
import (
"errors"
"fmt"
"strings"
"time"
)
// Message represents an email message to be sent.
type Message struct {
To []string // Required: recipient email addresses
Cc []string // Optional: carbon copy recipients
Bcc []string // Optional: blind carbon copy recipients
Subject string // Required: email subject
Body string // Required: email body content
IsHTML bool // Whether the body is HTML (default: false for plain text)
ReplyTo string // Optional: reply-to address
}
// Validate checks that the message has all required fields.
func (m *Message) Validate() error {
if len(m.To) == 0 {
return errors.New("at least one recipient is required")
}
if m.Subject == "" {
return errors.New("subject is required")
}
if m.Body == "" {
return errors.New("body is required")
}
return nil
}
// Format creates an RFC 5322 formatted email message.
func (m *Message) Format(fromEmail, fromName string) string {
var sb strings.Builder
// From header
if fromName != "" {
sb.WriteString(fmt.Sprintf("From: %s <%s>\r\n", fromName, fromEmail))
} else {
sb.WriteString(fmt.Sprintf("From: %s\r\n", fromEmail))
}
// To header
sb.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(m.To, ", ")))
// Cc header (optional)
if len(m.Cc) > 0 {
sb.WriteString(fmt.Sprintf("Cc: %s\r\n", strings.Join(m.Cc, ", ")))
}
// Reply-To header (optional)
if m.ReplyTo != "" {
sb.WriteString(fmt.Sprintf("Reply-To: %s\r\n", m.ReplyTo))
}
// Subject header
sb.WriteString(fmt.Sprintf("Subject: %s\r\n", m.Subject))
// Date header (RFC 5322 format)
sb.WriteString(fmt.Sprintf("Date: %s\r\n", time.Now().Format(time.RFC1123Z)))
// MIME headers
sb.WriteString("MIME-Version: 1.0\r\n")
// Content-Type header
if m.IsHTML {
sb.WriteString("Content-Type: text/html; charset=utf-8\r\n")
} else {
sb.WriteString("Content-Type: text/plain; charset=utf-8\r\n")
}
// Empty line separating headers from body
sb.WriteString("\r\n")
// Body
sb.WriteString(m.Body)
return sb.String()
}
// GetAllRecipients returns all recipients (To, Cc, Bcc) as a single slice.
func (m *Message) GetAllRecipients() []string {
var recipients []string
recipients = append(recipients, m.To...)
recipients = append(recipients, m.Cc...)
recipients = append(recipients, m.Bcc...)
return recipients
}
+181
View File
@@ -0,0 +1,181 @@
package email
import (
"strings"
"testing"
)
func TestMessageValidation(t *testing.T) {
tests := []struct {
name string
msg Message
wantErr bool
}{
{
name: "valid message",
msg: Message{
To: []string{"user@example.com"},
Subject: "Test Subject",
Body: "Test Body",
},
wantErr: false,
},
{
name: "no recipients",
msg: Message{
To: []string{},
Subject: "Test Subject",
Body: "Test Body",
},
wantErr: true,
},
{
name: "no subject",
msg: Message{
To: []string{"user@example.com"},
Subject: "",
Body: "Test Body",
},
wantErr: true,
},
{
name: "no body",
msg: Message{
To: []string{"user@example.com"},
Subject: "Test Subject",
Body: "",
},
wantErr: true,
},
{
name: "multiple recipients",
msg: Message{
To: []string{"user1@example.com", "user2@example.com"},
Cc: []string{"cc@example.com"},
Subject: "Test Subject",
Body: "Test Body",
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.msg.Validate()
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestMessageFormatPlainText(t *testing.T) {
msg := Message{
To: []string{"user@example.com"},
Subject: "Test Subject",
Body: "Test Body",
IsHTML: false,
}
formatted := msg.Format("sender@example.com", "Sender Name")
// Check required headers
if !strings.Contains(formatted, "From: Sender Name <sender@example.com>") {
t.Error("Missing or incorrect From header")
}
if !strings.Contains(formatted, "To: user@example.com") {
t.Error("Missing or incorrect To header")
}
if !strings.Contains(formatted, "Subject: Test Subject") {
t.Error("Missing or incorrect Subject header")
}
if !strings.Contains(formatted, "Content-Type: text/plain; charset=utf-8") {
t.Error("Missing or incorrect Content-Type header for plain text")
}
if !strings.Contains(formatted, "Test Body") {
t.Error("Missing message body")
}
}
func TestMessageFormatHTML(t *testing.T) {
msg := Message{
To: []string{"user@example.com"},
Subject: "Test Subject",
Body: "<html><body>Test Body</body></html>",
IsHTML: true,
}
formatted := msg.Format("sender@example.com", "Sender Name")
// Check HTML content-type
if !strings.Contains(formatted, "Content-Type: text/html; charset=utf-8") {
t.Error("Missing or incorrect Content-Type header for HTML")
}
if !strings.Contains(formatted, "<html><body>Test Body</body></html>") {
t.Error("Missing HTML body")
}
}
func TestMessageFormatMultipleRecipients(t *testing.T) {
msg := Message{
To: []string{"user1@example.com", "user2@example.com"},
Cc: []string{"cc1@example.com", "cc2@example.com"},
Bcc: []string{"bcc@example.com"},
Subject: "Test Subject",
Body: "Test Body",
ReplyTo: "reply@example.com",
}
formatted := msg.Format("sender@example.com", "Sender Name")
// Check To header formatting
if !strings.Contains(formatted, "To: user1@example.com, user2@example.com") {
t.Error("Missing or incorrect To header with multiple recipients")
}
// Check Cc header formatting
if !strings.Contains(formatted, "Cc: cc1@example.com, cc2@example.com") {
t.Error("Missing or incorrect Cc header")
}
// Bcc should NOT appear in the formatted message
if strings.Contains(formatted, "Bcc:") {
t.Error("Bcc header should not appear in formatted message")
}
// Check Reply-To header
if !strings.Contains(formatted, "Reply-To: reply@example.com") {
t.Error("Missing or incorrect Reply-To header")
}
}
func TestGetAllRecipients(t *testing.T) {
msg := Message{
To: []string{"user1@example.com", "user2@example.com"},
Cc: []string{"cc@example.com"},
Bcc: []string{"bcc@example.com"},
}
recipients := msg.GetAllRecipients()
// Should have all 4 recipients
if len(recipients) != 4 {
t.Errorf("GetAllRecipients() returned %d recipients, want 4", len(recipients))
}
// Check all recipients are present
expectedRecipients := map[string]bool{
"user1@example.com": true,
"user2@example.com": true,
"cc@example.com": true,
"bcc@example.com": true,
}
for _, recipient := range recipients {
if !expectedRecipients[recipient] {
t.Errorf("Unexpected recipient: %s", recipient)
}
delete(expectedRecipients, recipient)
}
if len(expectedRecipients) > 0 {
t.Error("Not all expected recipients were returned")
}
}
+50
View File
@@ -0,0 +1,50 @@
# Maintaining the Memo Filter Engine
The engine is memo-specific; any future field or behavior changes must stay
consistent with the memo schema and store implementations. Use this guide when
extending or debugging the package.
## Adding a New Memo Field
1. **Update the schema**
- Add the field entry in `schema.go`.
- Define the backing column (`Column`), JSON path (if applicable), type, and
allowed operators.
- Include the CEL variable in `EnvOptions`.
2. **Adjust parser or renderer (if needed)**
- For non-scalar fields (JSON booleans, lists), add handling in
`parser.go` or extend the renderer helpers.
- Keep validation in the parser (e.g., reject unsupported operators).
3. **Write a golden test**
- Extend the dialect-specific memo filter tests under
`store/db/{sqlite,mysql,postgres}/memo_filter_test.go` with a case that
exercises the new field.
4. **Run `go test ./...`** to ensure the SQL output matches expectations across
all dialects.
## Supporting Dialect Nuances
- Centralize differences inside `render.go`. If a new dialect-specific behavior
emerges (e.g., JSON operators), add the logic there rather than leaking it
into store code.
- Use the renderer helpers (`jsonExtractExpr`, `jsonArrayExpr`, etc.) rather than
sprinkling ad-hoc SQL strings.
- When placeholders change, adjust `addArg` so that argument numbering stays in
sync with store queries.
## Debugging Tips
- **Parser errors** Most originate in `buildCondition` or schema validation.
Enable logging around `parser.go` when diagnosing unknown identifier/operator
messages.
- **Renderer output** Temporary printf/log statements in `renderCondition` help
identify which IR node produced unexpected SQL.
- **Store integration** Ensure drivers call `filter.DefaultEngine()` exactly once
per process; the singleton caches the parsed CEL environment.
## Testing Checklist
- `go test ./store/...` ensures all dialect tests consume the engine correctly.
- Add targeted unit tests whenever new IR nodes or renderer paths are introduced.
- When changing boolean or JSON handling, verify all three dialect test suites
(SQLite, MySQL, Postgres) to avoid regression.
+63
View File
@@ -0,0 +1,63 @@
# Memo Filter Engine
This package houses the memo-only filter engine that turns CEL expressions into
SQL fragments. The engine follows a three phase pipeline inspired by systems
such as Calcite or Prisma:
1. **Parsing** CEL expressions are parsed with `cel-go` and validated against
the memo-specific environment declared in `schema.go`. Only fields that
exist in the schema can surface in the filter.
2. **Normalization** the raw CEL AST is converted into an intermediate
representation (IR) defined in `ir.go`. The IR is a dialect-agnostic tree of
conditions (logical operators, comparisons, list membership, etc.). This
step enforces schema rules (e.g. operator compatibility, type checks).
3. **Rendering** the renderer in `render.go` walks the IR and produces a SQL
fragment plus placeholder arguments tailored to a target dialect
(`sqlite`, `mysql`, or `postgres`). Dialect differences such as JSON access,
boolean semantics, placeholders, and `LIKE` vs `ILIKE` are encapsulated in
renderer helpers.
The entry point is `filter.DefaultEngine()` from `engine.go`. It lazily constructs
an `Engine` configured with the memo schema and exposes:
```go
engine, _ := filter.DefaultEngine()
stmt, _ := engine.CompileToStatement(ctx, `has_task_list && visibility == "PUBLIC"`, filter.RenderOptions{
Dialect: filter.DialectPostgres,
})
// stmt.SQL -> "((memo.payload->'property'->>'hasTaskList')::boolean IS TRUE AND memo.visibility = $1)"
// stmt.Args -> ["PUBLIC"]
```
## Core Files
| File | Responsibility |
| ------------- | ------------------------------------------------------------------------------- |
| `schema.go` | Declares memo fields, their types, backing columns, CEL environment options |
| `ir.go` | IR node definitions used across the pipeline |
| `parser.go` | Converts CEL `Expr` into IR while applying schema validation |
| `render.go` | Translates IR into SQL, handling dialect-specific behavior |
| `engine.go` | Glue between the phases; exposes `Compile`, `CompileToStatement`, and `DefaultEngine` |
| `helpers.go` | Convenience helpers for store integration (appending conditions) |
## SQL Generation Notes
- **Placeholders** — `?` is used for SQLite/MySQL, `$n` for Postgres. The renderer
tracks offsets to compose queries with pre-existing arguments.
- **JSON Fields** — Memo metadata lives in `memo.payload`. The renderer handles
`JSON_EXTRACT`/`json_extract`/`->`/`->>` variations and boolean coercion.
- **Tag Operations** — `tag in [...]` and `"tag" in tags` become JSON array
predicates. SQLite uses `LIKE` patterns, MySQL uses `JSON_CONTAINS`, and
Postgres uses `@>`.
- **Boolean Flags** — Fields such as `has_task_list` render as `IS TRUE` equality
checks, or comparisons against `CAST('true' AS JSON)` depending on the dialect.
## Typical Integration
1. Fetch the engine with `filter.DefaultEngine()`.
2. Call `CompileToStatement` using the appropriate dialect enum.
3. Append the emitted SQL fragment/args to the existing `WHERE` clause.
4. Execute the resulting query through the store driver.
The `helpers.AppendConditions` helper encapsulates steps 23 when a driver needs
to process an array of filters.
+191
View File
@@ -0,0 +1,191 @@
package filter
import (
"context"
"fmt"
"strings"
"sync"
"github.com/google/cel-go/cel"
"github.com/pkg/errors"
)
// Engine parses CEL filters into a dialect-agnostic condition tree.
type Engine struct {
schema Schema
env *cel.Env
}
// NewEngine builds a new Engine for the provided schema.
func NewEngine(schema Schema) (*Engine, error) {
env, err := cel.NewEnv(schema.EnvOptions...)
if err != nil {
return nil, errors.Wrap(err, "failed to create CEL environment")
}
return &Engine{
schema: schema,
env: env,
}, nil
}
// Program stores a compiled filter condition.
type Program struct {
schema Schema
condition Condition
}
// ConditionTree exposes the underlying condition tree.
func (p *Program) ConditionTree() Condition {
return p.condition
}
// Compile parses the filter string into an executable program.
func (e *Engine) Compile(_ context.Context, filter string) (*Program, error) {
if strings.TrimSpace(filter) == "" {
return nil, errors.New("filter expression is empty")
}
filter = normalizeLegacyFilter(filter)
ast, issues := e.env.Compile(filter)
if issues != nil && issues.Err() != nil {
return nil, errors.Wrap(issues.Err(), "failed to compile filter")
}
parsed, err := cel.AstToParsedExpr(ast)
if err != nil {
return nil, errors.Wrap(err, "failed to convert AST")
}
cond, err := buildCondition(parsed.GetExpr(), e.schema)
if err != nil {
return nil, err
}
return &Program{
schema: e.schema,
condition: cond,
}, nil
}
// CompileToStatement compiles and renders the filter in a single step.
func (e *Engine) CompileToStatement(ctx context.Context, filter string, opts RenderOptions) (Statement, error) {
program, err := e.Compile(ctx, filter)
if err != nil {
return Statement{}, err
}
return program.Render(opts)
}
// RenderOptions configure SQL rendering.
type RenderOptions struct {
Dialect DialectName
PlaceholderOffset int
DisableNullChecks bool
}
// Statement contains the rendered SQL fragment and its args.
type Statement struct {
SQL string
Args []any
}
// Render converts the program into a dialect-specific SQL fragment.
func (p *Program) Render(opts RenderOptions) (Statement, error) {
renderer := newRenderer(p.schema, opts)
return renderer.Render(p.condition)
}
var (
defaultOnce sync.Once
defaultInst *Engine
defaultErr error
defaultAttachmentOnce sync.Once
defaultAttachmentInst *Engine
defaultAttachmentErr error
)
// DefaultEngine returns the process-wide memo filter engine.
func DefaultEngine() (*Engine, error) {
defaultOnce.Do(func() {
defaultInst, defaultErr = NewEngine(NewSchema())
})
return defaultInst, defaultErr
}
// DefaultAttachmentEngine returns the process-wide attachment filter engine.
func DefaultAttachmentEngine() (*Engine, error) {
defaultAttachmentOnce.Do(func() {
defaultAttachmentInst, defaultAttachmentErr = NewEngine(NewAttachmentSchema())
})
return defaultAttachmentInst, defaultAttachmentErr
}
func normalizeLegacyFilter(expr string) string {
expr = rewriteNumericLogicalOperand(expr, "&&")
expr = rewriteNumericLogicalOperand(expr, "||")
return expr
}
func rewriteNumericLogicalOperand(expr, op string) string {
var builder strings.Builder
n := len(expr)
i := 0
var inQuote rune
for i < n {
ch := expr[i]
if inQuote != 0 {
builder.WriteByte(ch)
if ch == '\\' && i+1 < n {
builder.WriteByte(expr[i+1])
i += 2
continue
}
if ch == byte(inQuote) {
inQuote = 0
}
i++
continue
}
if ch == '\'' || ch == '"' {
inQuote = rune(ch)
builder.WriteByte(ch)
i++
continue
}
if strings.HasPrefix(expr[i:], op) {
builder.WriteString(op)
i += len(op)
// Preserve whitespace following the operator.
wsStart := i
for i < n && (expr[i] == ' ' || expr[i] == '\t') {
i++
}
builder.WriteString(expr[wsStart:i])
signStart := i
if i < n && (expr[i] == '+' || expr[i] == '-') {
i++
}
for i < n && expr[i] >= '0' && expr[i] <= '9' {
i++
}
if i > signStart {
numLiteral := expr[signStart:i]
builder.WriteString(fmt.Sprintf("(%s != 0)", numLiteral))
} else {
builder.WriteString(expr[signStart:i])
}
continue
}
builder.WriteByte(ch)
i++
}
return builder.String()
}
+25
View File
@@ -0,0 +1,25 @@
package filter
import (
"context"
"fmt"
)
// AppendConditions compiles the provided filters and appends the resulting SQL fragments and args.
func AppendConditions(ctx context.Context, engine *Engine, filters []string, dialect DialectName, where *[]string, args *[]any) error {
for _, filterStr := range filters {
stmt, err := engine.CompileToStatement(ctx, filterStr, RenderOptions{
Dialect: dialect,
PlaceholderOffset: len(*args),
})
if err != nil {
return err
}
if stmt.SQL == "" {
continue
}
*where = append(*where, fmt.Sprintf("(%s)", stmt.SQL))
*args = append(*args, stmt.Args...)
}
return nil
}
+159
View File
@@ -0,0 +1,159 @@
package filter
// Condition represents a boolean expression derived from the CEL filter.
type Condition interface {
isCondition()
}
// LogicalOperator enumerates the supported logical operators.
type LogicalOperator string
const (
LogicalAnd LogicalOperator = "AND"
LogicalOr LogicalOperator = "OR"
)
// LogicalCondition composes two conditions with a logical operator.
type LogicalCondition struct {
Operator LogicalOperator
Left Condition
Right Condition
}
func (*LogicalCondition) isCondition() {}
// NotCondition negates a child condition.
type NotCondition struct {
Expr Condition
}
func (*NotCondition) isCondition() {}
// FieldPredicateCondition asserts that a field evaluates to true.
type FieldPredicateCondition struct {
Field string
}
func (*FieldPredicateCondition) isCondition() {}
// ComparisonOperator lists supported comparison operators.
type ComparisonOperator string
const (
CompareEq ComparisonOperator = "="
CompareNeq ComparisonOperator = "!="
CompareLt ComparisonOperator = "<"
CompareLte ComparisonOperator = "<="
CompareGt ComparisonOperator = ">"
CompareGte ComparisonOperator = ">="
)
// ComparisonCondition represents a binary comparison.
type ComparisonCondition struct {
Left ValueExpr
Operator ComparisonOperator
Right ValueExpr
}
func (*ComparisonCondition) isCondition() {}
// InCondition represents an IN predicate with literal list values.
type InCondition struct {
Left ValueExpr
Values []ValueExpr
}
func (*InCondition) isCondition() {}
// ElementInCondition represents the CEL syntax `"value" in field`.
type ElementInCondition struct {
Element ValueExpr
Field string
}
func (*ElementInCondition) isCondition() {}
// ContainsCondition models the <field>.contains(<value>) call.
type ContainsCondition struct {
Field string
Value string
}
func (*ContainsCondition) isCondition() {}
// ConstantCondition captures a literal boolean outcome.
type ConstantCondition struct {
Value bool
}
func (*ConstantCondition) isCondition() {}
// ValueExpr models arithmetic or scalar expressions whose result feeds a comparison.
type ValueExpr interface {
isValueExpr()
}
// FieldRef references a named schema field.
type FieldRef struct {
Name string
}
func (*FieldRef) isValueExpr() {}
// LiteralValue holds a literal scalar.
type LiteralValue struct {
Value interface{}
}
func (*LiteralValue) isValueExpr() {}
// FunctionValue captures simple function calls like size(tags).
type FunctionValue struct {
Name string
Args []ValueExpr
}
func (*FunctionValue) isValueExpr() {}
// ListComprehensionCondition represents CEL macros like exists(), all(), filter().
type ListComprehensionCondition struct {
Kind ComprehensionKind
Field string // The list field to iterate over (e.g., "tags")
IterVar string // The iteration variable name (e.g., "t")
Predicate PredicateExpr // The predicate to evaluate for each element
}
func (*ListComprehensionCondition) isCondition() {}
// ComprehensionKind enumerates the types of list comprehensions.
type ComprehensionKind string
const (
ComprehensionExists ComprehensionKind = "exists"
)
// PredicateExpr represents predicates used in comprehensions.
type PredicateExpr interface {
isPredicateExpr()
}
// StartsWithPredicate represents t.startsWith("prefix").
type StartsWithPredicate struct {
Prefix string
}
func (*StartsWithPredicate) isPredicateExpr() {}
// EndsWithPredicate represents t.endsWith("suffix").
type EndsWithPredicate struct {
Suffix string
}
func (*EndsWithPredicate) isPredicateExpr() {}
// ContainsPredicate represents t.contains("substring").
type ContainsPredicate struct {
Substring string
}
func (*ContainsPredicate) isPredicateExpr() {}
+586
View File
@@ -0,0 +1,586 @@
package filter
import (
"time"
"github.com/pkg/errors"
exprv1 "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
func buildCondition(expr *exprv1.Expr, schema Schema) (Condition, error) {
switch v := expr.ExprKind.(type) {
case *exprv1.Expr_CallExpr:
return buildCallCondition(v.CallExpr, schema)
case *exprv1.Expr_ConstExpr:
val, err := getConstValue(expr)
if err != nil {
return nil, err
}
switch v := val.(type) {
case bool:
return &ConstantCondition{Value: v}, nil
case int64:
return &ConstantCondition{Value: v != 0}, nil
case float64:
return &ConstantCondition{Value: v != 0}, nil
default:
return nil, errors.New("filter must evaluate to a boolean value")
}
case *exprv1.Expr_IdentExpr:
name := v.IdentExpr.GetName()
field, ok := schema.Field(name)
if !ok {
return nil, errors.Errorf("unknown identifier %q", name)
}
if field.Type != FieldTypeBool {
return nil, errors.Errorf("identifier %q is not boolean", name)
}
return &FieldPredicateCondition{Field: name}, nil
case *exprv1.Expr_ComprehensionExpr:
return buildComprehensionCondition(v.ComprehensionExpr, schema)
default:
return nil, errors.New("unsupported top-level expression")
}
}
func buildCallCondition(call *exprv1.Expr_Call, schema Schema) (Condition, error) {
switch call.Function {
case "_&&_":
if len(call.Args) != 2 {
return nil, errors.New("logical AND expects two arguments")
}
left, err := buildCondition(call.Args[0], schema)
if err != nil {
return nil, err
}
right, err := buildCondition(call.Args[1], schema)
if err != nil {
return nil, err
}
return &LogicalCondition{
Operator: LogicalAnd,
Left: left,
Right: right,
}, nil
case "_||_":
if len(call.Args) != 2 {
return nil, errors.New("logical OR expects two arguments")
}
left, err := buildCondition(call.Args[0], schema)
if err != nil {
return nil, err
}
right, err := buildCondition(call.Args[1], schema)
if err != nil {
return nil, err
}
return &LogicalCondition{
Operator: LogicalOr,
Left: left,
Right: right,
}, nil
case "!_":
if len(call.Args) != 1 {
return nil, errors.New("logical NOT expects one argument")
}
child, err := buildCondition(call.Args[0], schema)
if err != nil {
return nil, err
}
return &NotCondition{Expr: child}, nil
case "_==_", "_!=_", "_<_", "_>_", "_<=_", "_>=_":
return buildComparisonCondition(call, schema)
case "@in":
return buildInCondition(call, schema)
case "contains":
return buildContainsCondition(call, schema)
default:
val, ok, err := evaluateBool(call)
if err != nil {
return nil, err
}
if ok {
return &ConstantCondition{Value: val}, nil
}
return nil, errors.Errorf("unsupported call expression %q", call.Function)
}
}
func buildComparisonCondition(call *exprv1.Expr_Call, schema Schema) (Condition, error) {
if len(call.Args) != 2 {
return nil, errors.New("comparison expects two arguments")
}
op, err := toComparisonOperator(call.Function)
if err != nil {
return nil, err
}
left, err := buildValueExpr(call.Args[0], schema)
if err != nil {
return nil, err
}
right, err := buildValueExpr(call.Args[1], schema)
if err != nil {
return nil, err
}
// If the left side is a field, validate allowed operators.
if field, ok := left.(*FieldRef); ok {
def, exists := schema.Field(field.Name)
if !exists {
return nil, errors.Errorf("unknown identifier %q", field.Name)
}
if def.Kind == FieldKindVirtualAlias {
def, exists = schema.ResolveAlias(field.Name)
if !exists {
return nil, errors.Errorf("invalid alias %q", field.Name)
}
}
if def.AllowedComparisonOps != nil {
if _, allowed := def.AllowedComparisonOps[op]; !allowed {
return nil, errors.Errorf("operator %s not allowed for field %q", op, field.Name)
}
}
}
return &ComparisonCondition{
Left: left,
Operator: op,
Right: right,
}, nil
}
func buildInCondition(call *exprv1.Expr_Call, schema Schema) (Condition, error) {
if len(call.Args) != 2 {
return nil, errors.New("in operator expects two arguments")
}
// Handle identifier in list syntax.
if identName, err := getIdentName(call.Args[0]); err == nil {
if field, ok := schema.Field(identName); ok && field.Kind == FieldKindVirtualAlias {
if _, aliasOk := schema.ResolveAlias(identName); !aliasOk {
return nil, errors.Errorf("invalid alias %q", identName)
}
} else if !ok {
return nil, errors.Errorf("unknown identifier %q", identName)
}
if listExpr := call.Args[1].GetListExpr(); listExpr != nil {
values := make([]ValueExpr, 0, len(listExpr.Elements))
for _, element := range listExpr.Elements {
value, err := buildValueExpr(element, schema)
if err != nil {
return nil, err
}
values = append(values, value)
}
return &InCondition{
Left: &FieldRef{Name: identName},
Values: values,
}, nil
}
}
// Handle "value in identifier" syntax.
if identName, err := getIdentName(call.Args[1]); err == nil {
if _, ok := schema.Field(identName); !ok {
return nil, errors.Errorf("unknown identifier %q", identName)
}
element, err := buildValueExpr(call.Args[0], schema)
if err != nil {
return nil, err
}
return &ElementInCondition{
Element: element,
Field: identName,
}, nil
}
return nil, errors.New("invalid use of in operator")
}
func buildContainsCondition(call *exprv1.Expr_Call, schema Schema) (Condition, error) {
if call.Target == nil {
return nil, errors.New("contains requires a target")
}
targetName, err := getIdentName(call.Target)
if err != nil {
return nil, err
}
field, ok := schema.Field(targetName)
if !ok {
return nil, errors.Errorf("unknown identifier %q", targetName)
}
if !field.SupportsContains {
return nil, errors.Errorf("identifier %q does not support contains()", targetName)
}
if len(call.Args) != 1 {
return nil, errors.New("contains expects exactly one argument")
}
value, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "contains only supports literal arguments")
}
str, ok := value.(string)
if !ok {
return nil, errors.New("contains argument must be a string")
}
return &ContainsCondition{
Field: targetName,
Value: str,
}, nil
}
func buildValueExpr(expr *exprv1.Expr, schema Schema) (ValueExpr, error) {
if identName, err := getIdentName(expr); err == nil {
if _, ok := schema.Field(identName); !ok {
return nil, errors.Errorf("unknown identifier %q", identName)
}
return &FieldRef{Name: identName}, nil
}
if literal, err := getConstValue(expr); err == nil {
return &LiteralValue{Value: literal}, nil
}
if value, ok, err := evaluateNumeric(expr); err != nil {
return nil, err
} else if ok {
return &LiteralValue{Value: value}, nil
}
if boolVal, ok, err := evaluateBoolExpr(expr); err != nil {
return nil, err
} else if ok {
return &LiteralValue{Value: boolVal}, nil
}
if call := expr.GetCallExpr(); call != nil {
switch call.Function {
case "size":
if len(call.Args) != 1 {
return nil, errors.New("size() expects one argument")
}
arg, err := buildValueExpr(call.Args[0], schema)
if err != nil {
return nil, err
}
return &FunctionValue{
Name: "size",
Args: []ValueExpr{arg},
}, nil
case "now":
return &LiteralValue{Value: timeNowUnix()}, nil
case "_+_", "_-_", "_*_":
value, ok, err := evaluateNumeric(expr)
if err != nil {
return nil, err
}
if ok {
return &LiteralValue{Value: value}, nil
}
default:
// Fall through to error return below
}
}
return nil, errors.New("unsupported value expression")
}
func toComparisonOperator(fn string) (ComparisonOperator, error) {
switch fn {
case "_==_":
return CompareEq, nil
case "_!=_":
return CompareNeq, nil
case "_<_":
return CompareLt, nil
case "_>_":
return CompareGt, nil
case "_<=_":
return CompareLte, nil
case "_>=_":
return CompareGte, nil
default:
return "", errors.Errorf("unsupported comparison operator %q", fn)
}
}
func getIdentName(expr *exprv1.Expr) (string, error) {
if ident := expr.GetIdentExpr(); ident != nil {
return ident.GetName(), nil
}
return "", errors.New("expression is not an identifier")
}
func getConstValue(expr *exprv1.Expr) (interface{}, error) {
v, ok := expr.ExprKind.(*exprv1.Expr_ConstExpr)
if !ok {
return nil, errors.New("expression is not a literal")
}
switch x := v.ConstExpr.ConstantKind.(type) {
case *exprv1.Constant_StringValue:
return v.ConstExpr.GetStringValue(), nil
case *exprv1.Constant_Int64Value:
return v.ConstExpr.GetInt64Value(), nil
case *exprv1.Constant_Uint64Value:
return int64(v.ConstExpr.GetUint64Value()), nil
case *exprv1.Constant_DoubleValue:
return v.ConstExpr.GetDoubleValue(), nil
case *exprv1.Constant_BoolValue:
return v.ConstExpr.GetBoolValue(), nil
case *exprv1.Constant_NullValue:
return nil, nil
default:
return nil, errors.Errorf("unsupported constant %T", x)
}
}
func evaluateBool(call *exprv1.Expr_Call) (bool, bool, error) {
val, ok, err := evaluateBoolExpr(&exprv1.Expr{ExprKind: &exprv1.Expr_CallExpr{CallExpr: call}})
return val, ok, err
}
func evaluateBoolExpr(expr *exprv1.Expr) (bool, bool, error) {
if literal, err := getConstValue(expr); err == nil {
if b, ok := literal.(bool); ok {
return b, true, nil
}
return false, false, nil
}
if call := expr.GetCallExpr(); call != nil && call.Function == "!_" {
if len(call.Args) != 1 {
return false, false, errors.New("NOT expects exactly one argument")
}
val, ok, err := evaluateBoolExpr(call.Args[0])
if err != nil || !ok {
return false, false, err
}
return !val, true, nil
}
return false, false, nil
}
func evaluateNumeric(expr *exprv1.Expr) (int64, bool, error) {
if literal, err := getConstValue(expr); err == nil {
switch v := literal.(type) {
case int64:
return v, true, nil
case float64:
return int64(v), true, nil
}
return 0, false, nil
}
call := expr.GetCallExpr()
if call == nil {
return 0, false, nil
}
switch call.Function {
case "now":
return timeNowUnix(), true, nil
case "_+_", "_-_", "_*_":
if len(call.Args) != 2 {
return 0, false, errors.New("arithmetic requires two arguments")
}
left, ok, err := evaluateNumeric(call.Args[0])
if err != nil {
return 0, false, err
}
if !ok {
return 0, false, nil
}
right, ok, err := evaluateNumeric(call.Args[1])
if err != nil {
return 0, false, err
}
if !ok {
return 0, false, nil
}
switch call.Function {
case "_+_":
return left + right, true, nil
case "_-_":
return left - right, true, nil
case "_*_":
return left * right, true, nil
default:
return 0, false, errors.Errorf("unsupported arithmetic operator %q", call.Function)
}
default:
return 0, false, nil
}
}
func timeNowUnix() int64 {
return time.Now().Unix()
}
// buildComprehensionCondition handles CEL comprehension expressions (exists, all, etc.).
func buildComprehensionCondition(comp *exprv1.Expr_Comprehension, schema Schema) (Condition, error) {
// Determine the comprehension kind by examining the loop initialization and step
kind, err := detectComprehensionKind(comp)
if err != nil {
return nil, err
}
// Get the field being iterated over
iterRangeIdent := comp.IterRange.GetIdentExpr()
if iterRangeIdent == nil {
return nil, errors.New("comprehension range must be a field identifier")
}
fieldName := iterRangeIdent.GetName()
// Validate the field
field, ok := schema.Field(fieldName)
if !ok {
return nil, errors.Errorf("unknown field %q in comprehension", fieldName)
}
if field.Kind != FieldKindJSONList {
return nil, errors.Errorf("field %q does not support comprehension (must be a list)", fieldName)
}
// Extract the predicate from the loop step
predicate, err := extractPredicate(comp, schema)
if err != nil {
return nil, err
}
return &ListComprehensionCondition{
Kind: kind,
Field: fieldName,
IterVar: comp.IterVar,
Predicate: predicate,
}, nil
}
// detectComprehensionKind determines if this is an exists() macro.
// Only exists() is currently supported.
func detectComprehensionKind(comp *exprv1.Expr_Comprehension) (ComprehensionKind, error) {
// Check the accumulator initialization
accuInit := comp.AccuInit.GetConstExpr()
if accuInit == nil {
return "", errors.New("comprehension accumulator must be initialized with a constant")
}
// exists() starts with false and uses OR (||) in loop step
if !accuInit.GetBoolValue() {
if step := comp.LoopStep.GetCallExpr(); step != nil && step.Function == "_||_" {
return ComprehensionExists, nil
}
}
// all() starts with true and uses AND (&&) - not supported
if accuInit.GetBoolValue() {
if step := comp.LoopStep.GetCallExpr(); step != nil && step.Function == "_&&_" {
return "", errors.New("all() comprehension is not supported; use exists() instead")
}
}
return "", errors.New("unsupported comprehension type; only exists() is supported")
}
// extractPredicate extracts the predicate expression from the comprehension loop step.
func extractPredicate(comp *exprv1.Expr_Comprehension, _ Schema) (PredicateExpr, error) {
// The loop step is: @result || predicate(t) for exists
// or: @result && predicate(t) for all
step := comp.LoopStep.GetCallExpr()
if step == nil {
return nil, errors.New("comprehension loop step must be a call expression")
}
if len(step.Args) != 2 {
return nil, errors.New("comprehension loop step must have two arguments")
}
// The predicate is the second argument
predicateExpr := step.Args[1]
predicateCall := predicateExpr.GetCallExpr()
if predicateCall == nil {
return nil, errors.New("comprehension predicate must be a function call")
}
// Handle different predicate functions
switch predicateCall.Function {
case "startsWith":
return buildStartsWithPredicate(predicateCall, comp.IterVar)
case "endsWith":
return buildEndsWithPredicate(predicateCall, comp.IterVar)
case "contains":
return buildContainsPredicate(predicateCall, comp.IterVar)
default:
return nil, errors.Errorf("unsupported predicate function %q in comprehension (supported: startsWith, endsWith, contains)", predicateCall.Function)
}
}
// buildStartsWithPredicate extracts the pattern from t.startsWith("prefix").
func buildStartsWithPredicate(call *exprv1.Expr_Call, iterVar string) (PredicateExpr, error) {
// Verify the target is the iteration variable
if target := call.Target.GetIdentExpr(); target == nil || target.GetName() != iterVar {
return nil, errors.Errorf("startsWith target must be the iteration variable %q", iterVar)
}
if len(call.Args) != 1 {
return nil, errors.New("startsWith expects exactly one argument")
}
prefix, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "startsWith argument must be a constant string")
}
prefixStr, ok := prefix.(string)
if !ok {
return nil, errors.New("startsWith argument must be a string")
}
return &StartsWithPredicate{Prefix: prefixStr}, nil
}
// buildEndsWithPredicate extracts the pattern from t.endsWith("suffix").
func buildEndsWithPredicate(call *exprv1.Expr_Call, iterVar string) (PredicateExpr, error) {
if target := call.Target.GetIdentExpr(); target == nil || target.GetName() != iterVar {
return nil, errors.Errorf("endsWith target must be the iteration variable %q", iterVar)
}
if len(call.Args) != 1 {
return nil, errors.New("endsWith expects exactly one argument")
}
suffix, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "endsWith argument must be a constant string")
}
suffixStr, ok := suffix.(string)
if !ok {
return nil, errors.New("endsWith argument must be a string")
}
return &EndsWithPredicate{Suffix: suffixStr}, nil
}
// buildContainsPredicate extracts the pattern from t.contains("substring").
func buildContainsPredicate(call *exprv1.Expr_Call, iterVar string) (PredicateExpr, error) {
if target := call.Target.GetIdentExpr(); target == nil || target.GetName() != iterVar {
return nil, errors.Errorf("contains target must be the iteration variable %q", iterVar)
}
if len(call.Args) != 1 {
return nil, errors.New("contains expects exactly one argument")
}
substring, err := getConstValue(call.Args[0])
if err != nil {
return nil, errors.Wrap(err, "contains argument must be a constant string")
}
substringStr, ok := substring.(string)
if !ok {
return nil, errors.New("contains argument must be a string")
}
return &ContainsPredicate{Substring: substringStr}, nil
}
+748
View File
@@ -0,0 +1,748 @@
package filter
import (
"fmt"
"strings"
"github.com/pkg/errors"
)
type renderer struct {
schema Schema
dialect DialectName
placeholderOffset int
placeholderCounter int
args []any
}
type renderResult struct {
sql string
trivial bool
unsatisfiable bool
}
func newRenderer(schema Schema, opts RenderOptions) *renderer {
return &renderer{
schema: schema,
dialect: opts.Dialect,
placeholderOffset: opts.PlaceholderOffset,
}
}
func (r *renderer) Render(cond Condition) (Statement, error) {
result, err := r.renderCondition(cond)
if err != nil {
return Statement{}, err
}
args := r.args
if args == nil {
args = []any{}
}
switch {
case result.unsatisfiable:
return Statement{
SQL: "1 = 0",
Args: args,
}, nil
case result.trivial:
return Statement{
SQL: "",
Args: args,
}, nil
default:
return Statement{
SQL: result.sql,
Args: args,
}, nil
}
}
func (r *renderer) renderCondition(cond Condition) (renderResult, error) {
switch c := cond.(type) {
case *LogicalCondition:
return r.renderLogicalCondition(c)
case *NotCondition:
return r.renderNotCondition(c)
case *FieldPredicateCondition:
return r.renderFieldPredicate(c)
case *ComparisonCondition:
return r.renderComparison(c)
case *InCondition:
return r.renderInCondition(c)
case *ElementInCondition:
return r.renderElementInCondition(c)
case *ContainsCondition:
return r.renderContainsCondition(c)
case *ListComprehensionCondition:
return r.renderListComprehension(c)
case *ConstantCondition:
if c.Value {
return renderResult{trivial: true}, nil
}
return renderResult{sql: "1 = 0", unsatisfiable: true}, nil
default:
return renderResult{}, errors.Errorf("unsupported condition type %T", c)
}
}
func (r *renderer) renderLogicalCondition(cond *LogicalCondition) (renderResult, error) {
left, err := r.renderCondition(cond.Left)
if err != nil {
return renderResult{}, err
}
right, err := r.renderCondition(cond.Right)
if err != nil {
return renderResult{}, err
}
switch cond.Operator {
case LogicalAnd:
return combineAnd(left, right), nil
case LogicalOr:
return combineOr(left, right), nil
default:
return renderResult{}, errors.Errorf("unsupported logical operator %s", cond.Operator)
}
}
func (r *renderer) renderNotCondition(cond *NotCondition) (renderResult, error) {
child, err := r.renderCondition(cond.Expr)
if err != nil {
return renderResult{}, err
}
if child.trivial {
return renderResult{sql: "1 = 0", unsatisfiable: true}, nil
}
if child.unsatisfiable {
return renderResult{trivial: true}, nil
}
return renderResult{
sql: fmt.Sprintf("NOT (%s)", child.sql),
}, nil
}
func (r *renderer) renderFieldPredicate(cond *FieldPredicateCondition) (renderResult, error) {
field, ok := r.schema.Field(cond.Field)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", cond.Field)
}
switch field.Kind {
case FieldKindBoolColumn:
column := qualifyColumn(r.dialect, field.Column)
return renderResult{
sql: fmt.Sprintf("%s IS TRUE", column),
}, nil
case FieldKindJSONBool:
sql, err := r.jsonBoolPredicate(field)
if err != nil {
return renderResult{}, err
}
return renderResult{sql: sql}, nil
default:
return renderResult{}, errors.Errorf("field %q cannot be used as a predicate", cond.Field)
}
}
func (r *renderer) renderComparison(cond *ComparisonCondition) (renderResult, error) {
switch left := cond.Left.(type) {
case *FieldRef:
field, ok := r.schema.Field(left.Name)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", left.Name)
}
switch field.Kind {
case FieldKindBoolColumn:
return r.renderBoolColumnComparison(field, cond.Operator, cond.Right)
case FieldKindJSONBool:
return r.renderJSONBoolComparison(field, cond.Operator, cond.Right)
case FieldKindScalar:
return r.renderScalarComparison(field, cond.Operator, cond.Right)
default:
return renderResult{}, errors.Errorf("field %q does not support comparison", field.Name)
}
case *FunctionValue:
return r.renderFunctionComparison(left, cond.Operator, cond.Right)
default:
return renderResult{}, errors.New("comparison must start with a field reference or supported function")
}
}
func (r *renderer) renderFunctionComparison(fn *FunctionValue, op ComparisonOperator, right ValueExpr) (renderResult, error) {
if fn.Name != "size" {
return renderResult{}, errors.Errorf("unsupported function %s in comparison", fn.Name)
}
if len(fn.Args) != 1 {
return renderResult{}, errors.New("size() expects one argument")
}
fieldArg, ok := fn.Args[0].(*FieldRef)
if !ok {
return renderResult{}, errors.New("size() argument must be a field")
}
field, ok := r.schema.Field(fieldArg.Name)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", fieldArg.Name)
}
if field.Kind != FieldKindJSONList {
return renderResult{}, errors.Errorf("size() only supports tag lists, got %q", field.Name)
}
value, err := expectNumericLiteral(right)
if err != nil {
return renderResult{}, err
}
expr := jsonArrayLengthExpr(r.dialect, field)
placeholder := r.addArg(value)
return renderResult{
sql: fmt.Sprintf("%s %s %s", expr, sqlOperator(op), placeholder),
}, nil
}
func (r *renderer) renderScalarComparison(field Field, op ComparisonOperator, right ValueExpr) (renderResult, error) {
lit, err := expectLiteral(right)
if err != nil {
return renderResult{}, err
}
columnExpr := field.columnExpr(r.dialect)
if lit == nil {
switch op {
case CompareEq:
return renderResult{sql: fmt.Sprintf("%s IS NULL", columnExpr)}, nil
case CompareNeq:
return renderResult{sql: fmt.Sprintf("%s IS NOT NULL", columnExpr)}, nil
default:
return renderResult{}, errors.Errorf("operator %s not supported for null comparison", op)
}
}
placeholder := ""
switch field.Type {
case FieldTypeString:
value, ok := lit.(string)
if !ok {
return renderResult{}, errors.Errorf("field %q expects string value", field.Name)
}
placeholder = r.addArg(value)
case FieldTypeInt, FieldTypeTimestamp:
num, err := toInt64(lit)
if err != nil {
return renderResult{}, errors.Wrapf(err, "field %q expects integer value", field.Name)
}
placeholder = r.addArg(num)
default:
return renderResult{}, errors.Errorf("unsupported data type %q for field %s", field.Type, field.Name)
}
return renderResult{
sql: fmt.Sprintf("%s %s %s", columnExpr, sqlOperator(op), placeholder),
}, nil
}
func (r *renderer) renderBoolColumnComparison(field Field, op ComparisonOperator, right ValueExpr) (renderResult, error) {
value, err := expectBool(right)
if err != nil {
return renderResult{}, err
}
placeholder := r.addBoolArg(value)
column := qualifyColumn(r.dialect, field.Column)
return renderResult{
sql: fmt.Sprintf("%s %s %s", column, sqlOperator(op), placeholder),
}, nil
}
func (r *renderer) renderJSONBoolComparison(field Field, op ComparisonOperator, right ValueExpr) (renderResult, error) {
value, err := expectBool(right)
if err != nil {
return renderResult{}, err
}
jsonExpr := jsonExtractExpr(r.dialect, field)
switch r.dialect {
case DialectSQLite:
switch op {
case CompareEq:
if field.Name == "has_task_list" {
target := "0"
if value {
target = "1"
}
return renderResult{sql: fmt.Sprintf("%s = %s", jsonExpr, target)}, nil
}
if value {
return renderResult{sql: fmt.Sprintf("%s IS TRUE", jsonExpr)}, nil
}
return renderResult{sql: fmt.Sprintf("NOT(%s IS TRUE)", jsonExpr)}, nil
case CompareNeq:
if field.Name == "has_task_list" {
target := "0"
if value {
target = "1"
}
return renderResult{sql: fmt.Sprintf("%s != %s", jsonExpr, target)}, nil
}
if value {
return renderResult{sql: fmt.Sprintf("NOT(%s IS TRUE)", jsonExpr)}, nil
}
return renderResult{sql: fmt.Sprintf("%s IS TRUE", jsonExpr)}, nil
default:
return renderResult{}, errors.Errorf("operator %s not supported for boolean JSON field", op)
}
case DialectMySQL:
boolStr := "false"
if value {
boolStr = "true"
}
return renderResult{
sql: fmt.Sprintf("%s %s CAST('%s' AS JSON)", jsonExpr, sqlOperator(op), boolStr),
}, nil
case DialectPostgres:
placeholder := r.addArg(value)
return renderResult{
sql: fmt.Sprintf("(%s)::boolean %s %s", jsonExpr, sqlOperator(op), placeholder),
}, nil
default:
return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
}
}
func (r *renderer) renderInCondition(cond *InCondition) (renderResult, error) {
fieldRef, ok := cond.Left.(*FieldRef)
if !ok {
return renderResult{}, errors.New("IN operator requires a field on the left-hand side")
}
if fieldRef.Name == "tag" {
return r.renderTagInList(cond.Values)
}
field, ok := r.schema.Field(fieldRef.Name)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", fieldRef.Name)
}
if field.Kind != FieldKindScalar {
return renderResult{}, errors.Errorf("field %q does not support IN()", fieldRef.Name)
}
return r.renderScalarInCondition(field, cond.Values)
}
func (r *renderer) renderTagInList(values []ValueExpr) (renderResult, error) {
field, ok := r.schema.ResolveAlias("tag")
if !ok {
return renderResult{}, errors.New("tag attribute is not configured")
}
conditions := make([]string, 0, len(values))
for _, v := range values {
lit, err := expectLiteral(v)
if err != nil {
return renderResult{}, err
}
str, ok := lit.(string)
if !ok {
return renderResult{}, errors.New("tags must be compared with string literals")
}
switch r.dialect {
case DialectSQLite:
// Support hierarchical tags: match exact tag OR tags with this prefix (e.g., "book" matches "book" and "book/something")
exactMatch := fmt.Sprintf("%s LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s"%%`, str)))
prefixMatch := fmt.Sprintf("%s LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s/%%`, str)))
expr := fmt.Sprintf("(%s OR %s)", exactMatch, prefixMatch)
conditions = append(conditions, expr)
case DialectMySQL:
// Support hierarchical tags: match exact tag OR tags with this prefix
exactMatch := fmt.Sprintf("JSON_CONTAINS(%s, %s)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
prefixMatch := fmt.Sprintf("%s LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s/%%`, str)))
expr := fmt.Sprintf("(%s OR %s)", exactMatch, prefixMatch)
conditions = append(conditions, expr)
case DialectPostgres:
// Support hierarchical tags: match exact tag OR tags with this prefix
exactMatch := fmt.Sprintf("%s @> jsonb_build_array(%s::json)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
prefixMatch := fmt.Sprintf("(%s)::text LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s/%%`, str)))
expr := fmt.Sprintf("(%s OR %s)", exactMatch, prefixMatch)
conditions = append(conditions, expr)
default:
return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
}
}
if len(conditions) == 1 {
return renderResult{sql: conditions[0]}, nil
}
return renderResult{
sql: fmt.Sprintf("(%s)", strings.Join(conditions, " OR ")),
}, nil
}
func (r *renderer) renderElementInCondition(cond *ElementInCondition) (renderResult, error) {
field, ok := r.schema.Field(cond.Field)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", cond.Field)
}
if field.Kind != FieldKindJSONList {
return renderResult{}, errors.Errorf("field %q is not a tag list", cond.Field)
}
lit, err := expectLiteral(cond.Element)
if err != nil {
return renderResult{}, err
}
str, ok := lit.(string)
if !ok {
return renderResult{}, errors.New("tags membership requires string literal")
}
switch r.dialect {
case DialectSQLite:
sql := fmt.Sprintf("%s LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s"%%`, str)))
return renderResult{sql: sql}, nil
case DialectMySQL:
sql := fmt.Sprintf("JSON_CONTAINS(%s, %s)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
return renderResult{sql: sql}, nil
case DialectPostgres:
sql := fmt.Sprintf("%s @> jsonb_build_array(%s::json)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
return renderResult{sql: sql}, nil
default:
return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
}
}
func (r *renderer) renderScalarInCondition(field Field, values []ValueExpr) (renderResult, error) {
placeholders := make([]string, 0, len(values))
for _, v := range values {
lit, err := expectLiteral(v)
if err != nil {
return renderResult{}, err
}
switch field.Type {
case FieldTypeString:
str, ok := lit.(string)
if !ok {
return renderResult{}, errors.Errorf("field %q expects string values", field.Name)
}
placeholders = append(placeholders, r.addArg(str))
case FieldTypeInt:
num, err := toInt64(lit)
if err != nil {
return renderResult{}, err
}
placeholders = append(placeholders, r.addArg(num))
default:
return renderResult{}, errors.Errorf("field %q does not support IN() comparisons", field.Name)
}
}
column := field.columnExpr(r.dialect)
return renderResult{
sql: fmt.Sprintf("%s IN (%s)", column, strings.Join(placeholders, ",")),
}, nil
}
func (r *renderer) renderContainsCondition(cond *ContainsCondition) (renderResult, error) {
field, ok := r.schema.Field(cond.Field)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", cond.Field)
}
column := field.columnExpr(r.dialect)
arg := fmt.Sprintf("%%%s%%", cond.Value)
switch r.dialect {
case DialectSQLite:
// Use custom Unicode-aware case folding function for case-insensitive comparison.
// This overcomes SQLite's ASCII-only LOWER() limitation.
sql := fmt.Sprintf("memos_unicode_lower(%s) LIKE memos_unicode_lower(%s)", column, r.addArg(arg))
return renderResult{sql: sql}, nil
case DialectPostgres:
sql := fmt.Sprintf("%s ILIKE %s", column, r.addArg(arg))
return renderResult{sql: sql}, nil
default:
sql := fmt.Sprintf("%s LIKE %s", column, r.addArg(arg))
return renderResult{sql: sql}, nil
}
}
func (r *renderer) renderListComprehension(cond *ListComprehensionCondition) (renderResult, error) {
field, ok := r.schema.Field(cond.Field)
if !ok {
return renderResult{}, errors.Errorf("unknown field %q", cond.Field)
}
if field.Kind != FieldKindJSONList {
return renderResult{}, errors.Errorf("field %q is not a JSON list", cond.Field)
}
// Render based on predicate type
switch pred := cond.Predicate.(type) {
case *StartsWithPredicate:
return r.renderTagStartsWith(field, pred.Prefix, cond.Kind)
case *EndsWithPredicate:
return r.renderTagEndsWith(field, pred.Suffix, cond.Kind)
case *ContainsPredicate:
return r.renderTagContains(field, pred.Substring, cond.Kind)
default:
return renderResult{}, errors.Errorf("unsupported predicate type %T in comprehension", pred)
}
}
// renderTagStartsWith generates SQL for tags.exists(t, t.startsWith("prefix")).
func (r *renderer) renderTagStartsWith(field Field, prefix string, _ ComprehensionKind) (renderResult, error) {
arrayExpr := jsonArrayExpr(r.dialect, field)
switch r.dialect {
case DialectSQLite, DialectMySQL:
// Match exact tag or tags with this prefix (hierarchical support)
exactMatch := r.buildJSONArrayLike(arrayExpr, fmt.Sprintf(`%%"%s"%%`, prefix))
prefixMatch := r.buildJSONArrayLike(arrayExpr, fmt.Sprintf(`%%"%s%%`, prefix))
condition := fmt.Sprintf("(%s OR %s)", exactMatch, prefixMatch)
return renderResult{sql: r.wrapWithNullCheck(arrayExpr, condition)}, nil
case DialectPostgres:
// Use PostgreSQL's powerful JSON operators
exactMatch := fmt.Sprintf("%s @> jsonb_build_array(%s::json)", arrayExpr, r.addArg(fmt.Sprintf(`"%s"`, prefix)))
prefixMatch := fmt.Sprintf("(%s)::text LIKE %s", arrayExpr, r.addArg(fmt.Sprintf(`%%"%s%%`, prefix)))
condition := fmt.Sprintf("(%s OR %s)", exactMatch, prefixMatch)
return renderResult{sql: r.wrapWithNullCheck(arrayExpr, condition)}, nil
default:
return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
}
}
// renderTagEndsWith generates SQL for tags.exists(t, t.endsWith("suffix")).
func (r *renderer) renderTagEndsWith(field Field, suffix string, _ ComprehensionKind) (renderResult, error) {
arrayExpr := jsonArrayExpr(r.dialect, field)
pattern := fmt.Sprintf(`%%%s"%%`, suffix)
likeExpr := r.buildJSONArrayLike(arrayExpr, pattern)
return renderResult{sql: r.wrapWithNullCheck(arrayExpr, likeExpr)}, nil
}
// renderTagContains generates SQL for tags.exists(t, t.contains("substring")).
func (r *renderer) renderTagContains(field Field, substring string, _ ComprehensionKind) (renderResult, error) {
arrayExpr := jsonArrayExpr(r.dialect, field)
pattern := fmt.Sprintf(`%%%s%%`, substring)
likeExpr := r.buildJSONArrayLike(arrayExpr, pattern)
return renderResult{sql: r.wrapWithNullCheck(arrayExpr, likeExpr)}, nil
}
// buildJSONArrayLike builds a LIKE expression for matching within a JSON array.
// Returns the LIKE clause without NULL/empty checks.
func (r *renderer) buildJSONArrayLike(arrayExpr, pattern string) string {
switch r.dialect {
case DialectSQLite, DialectMySQL:
return fmt.Sprintf("%s LIKE %s", arrayExpr, r.addArg(pattern))
case DialectPostgres:
return fmt.Sprintf("(%s)::text LIKE %s", arrayExpr, r.addArg(pattern))
default:
return ""
}
}
// wrapWithNullCheck wraps a condition with NULL and empty array checks.
// This ensures we don't match against NULL or empty JSON arrays.
func (r *renderer) wrapWithNullCheck(arrayExpr, condition string) string {
var nullCheck string
switch r.dialect {
case DialectSQLite:
nullCheck = fmt.Sprintf("%s IS NOT NULL AND %s != '[]'", arrayExpr, arrayExpr)
case DialectMySQL:
nullCheck = fmt.Sprintf("%s IS NOT NULL AND JSON_LENGTH(%s) > 0", arrayExpr, arrayExpr)
case DialectPostgres:
nullCheck = fmt.Sprintf("%s IS NOT NULL AND jsonb_array_length(%s) > 0", arrayExpr, arrayExpr)
default:
return condition
}
return fmt.Sprintf("(%s AND %s)", condition, nullCheck)
}
func (r *renderer) jsonBoolPredicate(field Field) (string, error) {
expr := jsonExtractExpr(r.dialect, field)
switch r.dialect {
case DialectSQLite:
return fmt.Sprintf("%s IS TRUE", expr), nil
case DialectMySQL:
return fmt.Sprintf("COALESCE(%s, CAST('false' AS JSON)) = CAST('true' AS JSON)", expr), nil
case DialectPostgres:
return fmt.Sprintf("(%s)::boolean IS TRUE", expr), nil
default:
return "", errors.Errorf("unsupported dialect %s", r.dialect)
}
}
func combineAnd(left, right renderResult) renderResult {
if left.unsatisfiable || right.unsatisfiable {
return renderResult{sql: "1 = 0", unsatisfiable: true}
}
if left.trivial {
return right
}
if right.trivial {
return left
}
return renderResult{
sql: fmt.Sprintf("(%s AND %s)", left.sql, right.sql),
}
}
func combineOr(left, right renderResult) renderResult {
if left.trivial || right.trivial {
return renderResult{trivial: true}
}
if left.unsatisfiable {
return right
}
if right.unsatisfiable {
return left
}
return renderResult{
sql: fmt.Sprintf("(%s OR %s)", left.sql, right.sql),
}
}
func (r *renderer) addArg(value any) string {
r.placeholderCounter++
r.args = append(r.args, value)
if r.dialect == DialectPostgres {
return fmt.Sprintf("$%d", r.placeholderOffset+r.placeholderCounter)
}
return "?"
}
func (r *renderer) addBoolArg(value bool) string {
var v any
switch r.dialect {
case DialectSQLite:
if value {
v = 1
} else {
v = 0
}
default:
v = value
}
return r.addArg(v)
}
func expectLiteral(expr ValueExpr) (any, error) {
lit, ok := expr.(*LiteralValue)
if !ok {
return nil, errors.New("expression must be a literal")
}
return lit.Value, nil
}
func expectBool(expr ValueExpr) (bool, error) {
lit, err := expectLiteral(expr)
if err != nil {
return false, err
}
value, ok := lit.(bool)
if !ok {
return false, errors.New("boolean literal required")
}
return value, nil
}
func expectNumericLiteral(expr ValueExpr) (int64, error) {
lit, err := expectLiteral(expr)
if err != nil {
return 0, err
}
return toInt64(lit)
}
func toInt64(value any) (int64, error) {
switch v := value.(type) {
case int:
return int64(v), nil
case int32:
return int64(v), nil
case int64:
return v, nil
case uint32:
return int64(v), nil
case uint64:
return int64(v), nil
case float32:
return int64(v), nil
case float64:
return int64(v), nil
default:
return 0, errors.Errorf("cannot convert %T to int64", value)
}
}
func sqlOperator(op ComparisonOperator) string {
return string(op)
}
func qualifyColumn(d DialectName, col Column) string {
switch d {
case DialectPostgres:
return fmt.Sprintf("%s.%s", col.Table, col.Name)
default:
return fmt.Sprintf("`%s`.`%s`", col.Table, col.Name)
}
}
func jsonPath(field Field) string {
return "$." + strings.Join(field.JSONPath, ".")
}
func jsonExtractExpr(d DialectName, field Field) string {
column := qualifyColumn(d, field.Column)
switch d {
case DialectSQLite, DialectMySQL:
return fmt.Sprintf("JSON_EXTRACT(%s, '%s')", column, jsonPath(field))
case DialectPostgres:
return buildPostgresJSONAccessor(column, field.JSONPath, true)
default:
return ""
}
}
func jsonArrayExpr(d DialectName, field Field) string {
column := qualifyColumn(d, field.Column)
switch d {
case DialectSQLite, DialectMySQL:
return fmt.Sprintf("JSON_EXTRACT(%s, '%s')", column, jsonPath(field))
case DialectPostgres:
return buildPostgresJSONAccessor(column, field.JSONPath, false)
default:
return ""
}
}
func jsonArrayLengthExpr(d DialectName, field Field) string {
arrayExpr := jsonArrayExpr(d, field)
switch d {
case DialectSQLite:
return fmt.Sprintf("JSON_ARRAY_LENGTH(COALESCE(%s, JSON_ARRAY()))", arrayExpr)
case DialectMySQL:
return fmt.Sprintf("JSON_LENGTH(COALESCE(%s, JSON_ARRAY()))", arrayExpr)
case DialectPostgres:
return fmt.Sprintf("jsonb_array_length(COALESCE(%s, '[]'::jsonb))", arrayExpr)
default:
return ""
}
}
func buildPostgresJSONAccessor(base string, path []string, terminalText bool) string {
expr := base
for idx, part := range path {
if idx == len(path)-1 && terminalText {
expr = fmt.Sprintf("%s->>'%s'", expr, part)
} else {
expr = fmt.Sprintf("%s->'%s'", expr, part)
}
}
return expr
}
+319
View File
@@ -0,0 +1,319 @@
package filter
import (
"fmt"
"time"
"github.com/google/cel-go/cel"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/common/types/ref"
)
// DialectName enumerates supported SQL dialects.
type DialectName string
const (
DialectSQLite DialectName = "sqlite"
DialectMySQL DialectName = "mysql"
DialectPostgres DialectName = "postgres"
)
// FieldType represents the logical type of a field.
type FieldType string
const (
FieldTypeString FieldType = "string"
FieldTypeInt FieldType = "int"
FieldTypeBool FieldType = "bool"
FieldTypeTimestamp FieldType = "timestamp"
)
// FieldKind describes how a field is stored.
type FieldKind string
const (
FieldKindScalar FieldKind = "scalar"
FieldKindBoolColumn FieldKind = "bool_column"
FieldKindJSONBool FieldKind = "json_bool"
FieldKindJSONList FieldKind = "json_list"
FieldKindVirtualAlias FieldKind = "virtual_alias"
)
// Column identifies the backing table column.
type Column struct {
Table string
Name string
}
// Field captures the schema metadata for an exposed CEL identifier.
type Field struct {
Name string
Kind FieldKind
Type FieldType
Column Column
JSONPath []string
AliasFor string
SupportsContains bool
Expressions map[DialectName]string
AllowedComparisonOps map[ComparisonOperator]bool
}
// Schema collects CEL environment options and field metadata.
type Schema struct {
Name string
Fields map[string]Field
EnvOptions []cel.EnvOption
}
// Field returns the field metadata if present.
func (s Schema) Field(name string) (Field, bool) {
f, ok := s.Fields[name]
return f, ok
}
// ResolveAlias resolves a virtual alias to its target field.
func (s Schema) ResolveAlias(name string) (Field, bool) {
field, ok := s.Fields[name]
if !ok {
return Field{}, false
}
if field.Kind == FieldKindVirtualAlias {
target, ok := s.Fields[field.AliasFor]
if !ok {
return Field{}, false
}
return target, true
}
return field, true
}
var nowFunction = cel.Function("now",
cel.Overload("now",
[]*cel.Type{},
cel.IntType,
cel.FunctionBinding(func(_ ...ref.Val) ref.Val {
return types.Int(time.Now().Unix())
}),
),
)
// NewSchema constructs the memo filter schema and CEL environment.
func NewSchema() Schema {
fields := map[string]Field{
"content": {
Name: "content",
Kind: FieldKindScalar,
Type: FieldTypeString,
Column: Column{Table: "memo", Name: "content"},
SupportsContains: true,
Expressions: map[DialectName]string{},
},
"creator_id": {
Name: "creator_id",
Kind: FieldKindScalar,
Type: FieldTypeInt,
Column: Column{Table: "memo", Name: "creator_id"},
Expressions: map[DialectName]string{},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"created_ts": {
Name: "created_ts",
Kind: FieldKindScalar,
Type: FieldTypeTimestamp,
Column: Column{Table: "memo", Name: "created_ts"},
Expressions: map[DialectName]string{
// MySQL stores created_ts as TIMESTAMP, needs conversion to epoch
DialectMySQL: "UNIX_TIMESTAMP(%s)",
// PostgreSQL and SQLite store created_ts as BIGINT (epoch), no conversion needed
DialectPostgres: "%s",
DialectSQLite: "%s",
},
},
"updated_ts": {
Name: "updated_ts",
Kind: FieldKindScalar,
Type: FieldTypeTimestamp,
Column: Column{Table: "memo", Name: "updated_ts"},
Expressions: map[DialectName]string{
// MySQL stores updated_ts as TIMESTAMP, needs conversion to epoch
DialectMySQL: "UNIX_TIMESTAMP(%s)",
// PostgreSQL and SQLite store updated_ts as BIGINT (epoch), no conversion needed
DialectPostgres: "%s",
DialectSQLite: "%s",
},
},
"pinned": {
Name: "pinned",
Kind: FieldKindBoolColumn,
Type: FieldTypeBool,
Column: Column{Table: "memo", Name: "pinned"},
Expressions: map[DialectName]string{},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"visibility": {
Name: "visibility",
Kind: FieldKindScalar,
Type: FieldTypeString,
Column: Column{Table: "memo", Name: "visibility"},
Expressions: map[DialectName]string{},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"tags": {
Name: "tags",
Kind: FieldKindJSONList,
Type: FieldTypeString,
Column: Column{Table: "memo", Name: "payload"},
JSONPath: []string{"tags"},
},
"tag": {
Name: "tag",
Kind: FieldKindVirtualAlias,
Type: FieldTypeString,
AliasFor: "tags",
},
"has_task_list": {
Name: "has_task_list",
Kind: FieldKindJSONBool,
Type: FieldTypeBool,
Column: Column{Table: "memo", Name: "payload"},
JSONPath: []string{"property", "hasTaskList"},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"has_link": {
Name: "has_link",
Kind: FieldKindJSONBool,
Type: FieldTypeBool,
Column: Column{Table: "memo", Name: "payload"},
JSONPath: []string{"property", "hasLink"},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"has_code": {
Name: "has_code",
Kind: FieldKindJSONBool,
Type: FieldTypeBool,
Column: Column{Table: "memo", Name: "payload"},
JSONPath: []string{"property", "hasCode"},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
"has_incomplete_tasks": {
Name: "has_incomplete_tasks",
Kind: FieldKindJSONBool,
Type: FieldTypeBool,
Column: Column{Table: "memo", Name: "payload"},
JSONPath: []string{"property", "hasIncompleteTasks"},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
}
envOptions := []cel.EnvOption{
cel.Variable("content", cel.StringType),
cel.Variable("creator_id", cel.IntType),
cel.Variable("created_ts", cel.IntType),
cel.Variable("updated_ts", cel.IntType),
cel.Variable("pinned", cel.BoolType),
cel.Variable("tag", cel.StringType),
cel.Variable("tags", cel.ListType(cel.StringType)),
cel.Variable("visibility", cel.StringType),
cel.Variable("has_task_list", cel.BoolType),
cel.Variable("has_link", cel.BoolType),
cel.Variable("has_code", cel.BoolType),
cel.Variable("has_incomplete_tasks", cel.BoolType),
nowFunction,
}
return Schema{
Name: "memo",
Fields: fields,
EnvOptions: envOptions,
}
}
// NewAttachmentSchema constructs the attachment filter schema and CEL environment.
func NewAttachmentSchema() Schema {
fields := map[string]Field{
"filename": {
Name: "filename",
Kind: FieldKindScalar,
Type: FieldTypeString,
Column: Column{Table: "attachment", Name: "filename"},
SupportsContains: true,
Expressions: map[DialectName]string{},
},
"mime_type": {
Name: "mime_type",
Kind: FieldKindScalar,
Type: FieldTypeString,
Column: Column{Table: "attachment", Name: "type"},
Expressions: map[DialectName]string{},
},
"create_time": {
Name: "create_time",
Kind: FieldKindScalar,
Type: FieldTypeTimestamp,
Column: Column{Table: "attachment", Name: "created_ts"},
Expressions: map[DialectName]string{
// MySQL stores created_ts as TIMESTAMP, needs conversion to epoch
DialectMySQL: "UNIX_TIMESTAMP(%s)",
// PostgreSQL and SQLite store created_ts as BIGINT (epoch), no conversion needed
DialectPostgres: "%s",
DialectSQLite: "%s",
},
},
"memo_id": {
Name: "memo_id",
Kind: FieldKindScalar,
Type: FieldTypeInt,
Column: Column{Table: "attachment", Name: "memo_id"},
Expressions: map[DialectName]string{},
AllowedComparisonOps: map[ComparisonOperator]bool{
CompareEq: true,
CompareNeq: true,
},
},
}
envOptions := []cel.EnvOption{
cel.Variable("filename", cel.StringType),
cel.Variable("mime_type", cel.StringType),
cel.Variable("create_time", cel.IntType),
cel.Variable("memo_id", cel.AnyType),
nowFunction,
}
return Schema{
Name: "attachment",
Fields: fields,
EnvOptions: envOptions,
}
}
// columnExpr returns the field expression for the given dialect, applying
// any schema-specific overrides (e.g. UNIX timestamp conversions).
func (f Field) columnExpr(d DialectName) string {
base := qualifyColumn(d, f.Column)
if expr, ok := f.Expressions[d]; ok && expr != "" {
return fmt.Sprintf(expr, base)
}
return base
}
+166
View File
@@ -0,0 +1,166 @@
package httpgetter
import (
"fmt"
"io"
"net"
"net/http"
"net/url"
"github.com/pkg/errors"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
var ErrInternalIP = errors.New("internal IP addresses are not allowed")
var httpClient = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if err := validateURL(req.URL.String()); err != nil {
return errors.Wrap(err, "redirect to internal IP")
}
if len(via) >= 10 {
return errors.New("too many redirects")
}
return nil
},
}
type HTMLMeta struct {
Title string `json:"title"`
Description string `json:"description"`
Image string `json:"image"`
}
func GetHTMLMeta(urlStr string) (*HTMLMeta, error) {
if err := validateURL(urlStr); err != nil {
return nil, err
}
response, err := httpClient.Get(urlStr)
if err != nil {
return nil, err
}
defer response.Body.Close()
mediatype, err := getMediatype(response)
if err != nil {
return nil, err
}
if mediatype != "text/html" {
return nil, errors.New("not a HTML page")
}
// TODO: limit the size of the response body
htmlMeta := extractHTMLMeta(response.Body)
enrichSiteMeta(response.Request.URL, htmlMeta)
return htmlMeta, nil
}
func extractHTMLMeta(resp io.Reader) *HTMLMeta {
tokenizer := html.NewTokenizer(resp)
htmlMeta := new(HTMLMeta)
for {
tokenType := tokenizer.Next()
if tokenType == html.ErrorToken {
break
} else if tokenType == html.StartTagToken || tokenType == html.SelfClosingTagToken {
token := tokenizer.Token()
if token.DataAtom == atom.Body {
break
}
if token.DataAtom == atom.Title {
tokenizer.Next()
token := tokenizer.Token()
htmlMeta.Title = token.Data
} else if token.DataAtom == atom.Meta {
description, ok := extractMetaProperty(token, "description")
if ok {
htmlMeta.Description = description
}
ogTitle, ok := extractMetaProperty(token, "og:title")
if ok {
htmlMeta.Title = ogTitle
}
ogDescription, ok := extractMetaProperty(token, "og:description")
if ok {
htmlMeta.Description = ogDescription
}
ogImage, ok := extractMetaProperty(token, "og:image")
if ok {
htmlMeta.Image = ogImage
}
}
}
}
return htmlMeta
}
func extractMetaProperty(token html.Token, prop string) (content string, ok bool) {
content, ok = "", false
for _, attr := range token.Attr {
if attr.Key == "property" && attr.Val == prop {
ok = true
}
if attr.Key == "content" {
content = attr.Val
}
}
return content, ok
}
func validateURL(urlStr string) error {
u, err := url.Parse(urlStr)
if err != nil {
return errors.New("invalid URL format")
}
if u.Scheme != "http" && u.Scheme != "https" {
return errors.New("only http/https protocols are allowed")
}
host := u.Hostname()
if host == "" {
return errors.New("empty hostname")
}
// check if the hostname is an IP
if ip := net.ParseIP(host); ip != nil {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
return errors.Wrap(ErrInternalIP, ip.String())
}
return nil
}
// check if it's a hostname, resolve it and check all returned IPs
ips, err := net.LookupIP(host)
if err != nil {
return errors.Errorf("failed to resolve hostname: %v", err)
}
for _, ip := range ips {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
return errors.Wrapf(ErrInternalIP, "host=%s, ip=%s", host, ip.String())
}
}
return nil
}
func enrichSiteMeta(url *url.URL, meta *HTMLMeta) {
if url.Hostname() == "www.youtube.com" {
if url.Path == "/watch" {
vid := url.Query().Get("v")
if vid != "" {
meta.Image = fmt.Sprintf("https://img.youtube.com/vi/%s/mqdefault.jpg", vid)
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
package httpgetter
import (
"errors"
"testing"
"github.com/stretchr/testify/require"
)
func TestGetHTMLMeta(t *testing.T) {
tests := []struct {
urlStr string
htmlMeta HTMLMeta
}{}
for _, test := range tests {
metadata, err := GetHTMLMeta(test.urlStr)
require.NoError(t, err)
require.Equal(t, test.htmlMeta, *metadata)
}
}
func TestGetHTMLMetaForInternal(t *testing.T) {
// test for internal IP
if _, err := GetHTMLMeta("http://192.168.0.1"); !errors.Is(err, ErrInternalIP) {
t.Errorf("Expected error for internal IP, got %v", err)
}
// test for resolved internal IP
if _, err := GetHTMLMeta("http://localhost"); !errors.Is(err, ErrInternalIP) {
t.Errorf("Expected error for resolved internal IP, got %v", err)
}
}
+1
View File
@@ -0,0 +1 @@
package httpgetter
+45
View File
@@ -0,0 +1,45 @@
package httpgetter
import (
"errors"
"io"
"net/http"
"net/url"
"strings"
)
type Image struct {
Blob []byte
Mediatype string
}
func GetImage(urlStr string) (*Image, error) {
if _, err := url.Parse(urlStr); err != nil {
return nil, err
}
response, err := http.Get(urlStr)
if err != nil {
return nil, err
}
defer response.Body.Close()
mediatype, err := getMediatype(response)
if err != nil {
return nil, err
}
if !strings.HasPrefix(mediatype, "image/") {
return nil, errors.New("wrong image mediatype")
}
bodyBytes, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}
image := &Image{
Blob: bodyBytes,
Mediatype: mediatype,
}
return image, nil
}
+15
View File
@@ -0,0 +1,15 @@
package httpgetter
import (
"mime"
"net/http"
)
func getMediatype(response *http.Response) (string, error) {
contentType := response.Header.Get("content-type")
mediatype, _, err := mime.ParseMediaType(contentType)
if err != nil {
return "", err
}
return mediatype, nil
}
+8
View File
@@ -0,0 +1,8 @@
package idp
type IdentityProviderUserInfo struct {
Identifier string
DisplayName string
Email string
AvatarURL string
}
+134
View File
@@ -0,0 +1,134 @@
// Package oauth2 is the plugin for OAuth2 Identity Provider.
package oauth2
import (
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"github.com/pkg/errors"
"golang.org/x/oauth2"
"github.com/usememos/memos/plugin/idp"
storepb "github.com/usememos/memos/proto/gen/store"
)
// IdentityProvider represents an OAuth2 Identity Provider.
type IdentityProvider struct {
config *storepb.OAuth2Config
}
// NewIdentityProvider initializes a new OAuth2 Identity Provider with the given configuration.
func NewIdentityProvider(config *storepb.OAuth2Config) (*IdentityProvider, error) {
for v, field := range map[string]string{
config.ClientId: "clientId",
config.ClientSecret: "clientSecret",
config.TokenUrl: "tokenUrl",
config.UserInfoUrl: "userInfoUrl",
config.FieldMapping.Identifier: "fieldMapping.identifier",
} {
if v == "" {
return nil, errors.Errorf(`the field "%s" is empty but required`, field)
}
}
return &IdentityProvider{
config: config,
}, nil
}
// ExchangeToken returns the exchanged OAuth2 token using the given authorization code.
// If codeVerifier is provided, it will be used for PKCE (Proof Key for Code Exchange) validation.
func (p *IdentityProvider) ExchangeToken(ctx context.Context, redirectURL, code, codeVerifier string) (string, error) {
conf := &oauth2.Config{
ClientID: p.config.ClientId,
ClientSecret: p.config.ClientSecret,
RedirectURL: redirectURL,
Scopes: p.config.Scopes,
Endpoint: oauth2.Endpoint{
AuthURL: p.config.AuthUrl,
TokenURL: p.config.TokenUrl,
AuthStyle: oauth2.AuthStyleInParams,
},
}
// Prepare token exchange options
opts := []oauth2.AuthCodeOption{}
// Add PKCE code_verifier if provided
if codeVerifier != "" {
opts = append(opts, oauth2.SetAuthURLParam("code_verifier", codeVerifier))
}
token, err := conf.Exchange(ctx, code, opts...)
if err != nil {
return "", errors.Wrap(err, "failed to exchange access token")
}
// Use the standard AccessToken field instead of Extra()
// This is more reliable across different OAuth providers
if token.AccessToken == "" {
return "", errors.New("missing access token from authorization response")
}
return token.AccessToken, nil
}
// UserInfo returns the parsed user information using the given OAuth2 token.
func (p *IdentityProvider) UserInfo(token string) (*idp.IdentityProviderUserInfo, error) {
client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, p.config.UserInfoUrl, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to new http request")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
resp, err := client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failed to get user information")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "failed to read response body")
}
var claims map[string]any
if err := json.Unmarshal(body, &claims); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal response body")
}
slog.Info("user info claims", "claims", claims)
userInfo := &idp.IdentityProviderUserInfo{}
if v, ok := claims[p.config.FieldMapping.Identifier].(string); ok {
userInfo.Identifier = v
}
if userInfo.Identifier == "" {
return nil, errors.Errorf("the field %q is not found in claims or has empty value", p.config.FieldMapping.Identifier)
}
// Best effort to map optional fields
if p.config.FieldMapping.DisplayName != "" {
if v, ok := claims[p.config.FieldMapping.DisplayName].(string); ok {
userInfo.DisplayName = v
}
}
if userInfo.DisplayName == "" {
userInfo.DisplayName = userInfo.Identifier
}
if p.config.FieldMapping.Email != "" {
if v, ok := claims[p.config.FieldMapping.Email].(string); ok {
userInfo.Email = v
}
}
if p.config.FieldMapping.AvatarUrl != "" {
if v, ok := claims[p.config.FieldMapping.AvatarUrl].(string); ok {
userInfo.AvatarURL = v
}
}
slog.Info("user info", "userInfo", userInfo)
return userInfo, nil
}
+164
View File
@@ -0,0 +1,164 @@
package oauth2
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/usememos/memos/plugin/idp"
storepb "github.com/usememos/memos/proto/gen/store"
)
func TestNewIdentityProvider(t *testing.T) {
tests := []struct {
name string
config *storepb.OAuth2Config
containsErr string
}{
{
name: "no tokenUrl",
config: &storepb.OAuth2Config{
ClientId: "test-client-id",
ClientSecret: "test-client-secret",
AuthUrl: "",
TokenUrl: "",
UserInfoUrl: "https://example.com/api/user",
FieldMapping: &storepb.FieldMapping{
Identifier: "login",
},
},
containsErr: `the field "tokenUrl" is empty but required`,
},
{
name: "no userInfoUrl",
config: &storepb.OAuth2Config{
ClientId: "test-client-id",
ClientSecret: "test-client-secret",
AuthUrl: "",
TokenUrl: "https://example.com/token",
UserInfoUrl: "",
FieldMapping: &storepb.FieldMapping{
Identifier: "login",
},
},
containsErr: `the field "userInfoUrl" is empty but required`,
},
{
name: "no field mapping identifier",
config: &storepb.OAuth2Config{
ClientId: "test-client-id",
ClientSecret: "test-client-secret",
AuthUrl: "",
TokenUrl: "https://example.com/token",
UserInfoUrl: "https://example.com/api/user",
FieldMapping: &storepb.FieldMapping{
Identifier: "",
},
},
containsErr: `the field "fieldMapping.identifier" is empty but required`,
},
}
for _, test := range tests {
t.Run(test.name, func(*testing.T) {
_, err := NewIdentityProvider(test.config)
assert.ErrorContains(t, err, test.containsErr)
})
}
}
func newMockServer(t *testing.T, code, accessToken string, userinfo []byte) *httptest.Server {
mux := http.NewServeMux()
var rawIDToken string
mux.HandleFunc("/oauth2/token", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
body, err := io.ReadAll(r.Body)
require.NoError(t, err)
vals, err := url.ParseQuery(string(body))
require.NoError(t, err)
require.Equal(t, code, vals.Get("code"))
require.Equal(t, "authorization_code", vals.Get("grant_type"))
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(map[string]any{
"access_token": accessToken,
"token_type": "Bearer",
"expires_in": 3600,
"id_token": rawIDToken,
})
require.NoError(t, err)
})
mux.HandleFunc("/oauth2/userinfo", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, err := w.Write(userinfo)
require.NoError(t, err)
})
s := httptest.NewServer(mux)
return s
}
func TestIdentityProvider(t *testing.T) {
ctx := context.Background()
const (
testClientID = "test-client-id"
testCode = "test-code"
testAccessToken = "test-access-token"
testSubject = "123456789"
testName = "John Doe"
testEmail = "john.doe@example.com"
)
userInfo, err := json.Marshal(
map[string]any{
"sub": testSubject,
"name": testName,
"email": testEmail,
},
)
require.NoError(t, err)
s := newMockServer(t, testCode, testAccessToken, userInfo)
oauth2, err := NewIdentityProvider(
&storepb.OAuth2Config{
ClientId: testClientID,
ClientSecret: "test-client-secret",
TokenUrl: fmt.Sprintf("%s/oauth2/token", s.URL),
UserInfoUrl: fmt.Sprintf("%s/oauth2/userinfo", s.URL),
FieldMapping: &storepb.FieldMapping{
Identifier: "sub",
DisplayName: "name",
Email: "email",
},
},
)
require.NoError(t, err)
redirectURL := "https://example.com/oauth/callback"
// Test without PKCE (backward compatibility)
oauthToken, err := oauth2.ExchangeToken(ctx, redirectURL, testCode, "")
require.NoError(t, err)
require.Equal(t, testAccessToken, oauthToken)
userInfoResult, err := oauth2.UserInfo(oauthToken)
require.NoError(t, err)
wantUserInfo := &idp.IdentityProviderUserInfo{
Identifier: testSubject,
DisplayName: testName,
Email: testEmail,
}
assert.Equal(t, wantUserInfo, userInfoResult)
}
+28
View File
@@ -0,0 +1,28 @@
package ast
import (
gast "github.com/yuin/goldmark/ast"
)
// TagNode represents a #tag in the markdown AST.
type TagNode struct {
gast.BaseInline
// Tag name without the # prefix
Tag []byte
}
// KindTag is the NodeKind for TagNode.
var KindTag = gast.NewNodeKind("Tag")
// Kind returns KindTag.
func (*TagNode) Kind() gast.NodeKind {
return KindTag
}
// Dump implements Node.Dump for debugging.
func (n *TagNode) Dump(source []byte, level int) {
gast.DumpHelper(n, source, level, map[string]string{
"Tag": string(n.Tag),
}, nil)
}
+24
View File
@@ -0,0 +1,24 @@
package extensions
import (
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/util"
mparser "github.com/usememos/memos/plugin/markdown/parser"
)
type tagExtension struct{}
// TagExtension is a goldmark extension for #tag syntax.
var TagExtension = &tagExtension{}
// Extend extends the goldmark parser with tag support.
func (*tagExtension) Extend(m goldmark.Markdown) {
m.Parser().AddOptions(
parser.WithInlineParsers(
// Priority 200 - run before standard link parser (500)
util.Prioritized(mparser.NewTagParser(), 200),
),
)
}
+409
View File
@@ -0,0 +1,409 @@
package markdown
import (
"bytes"
"strings"
"github.com/yuin/goldmark"
gast "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/extension"
east "github.com/yuin/goldmark/extension/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
mast "github.com/usememos/memos/plugin/markdown/ast"
"github.com/usememos/memos/plugin/markdown/extensions"
"github.com/usememos/memos/plugin/markdown/renderer"
storepb "github.com/usememos/memos/proto/gen/store"
)
// ExtractedData contains all metadata extracted from markdown in a single pass.
type ExtractedData struct {
Tags []string
Property *storepb.MemoPayload_Property
}
// Service handles markdown metadata extraction.
// It uses goldmark to parse markdown and extract tags, properties, and snippets.
// HTML rendering is primarily done on frontend using markdown-it, but backend provides
// RenderHTML for RSS feeds and other server-side rendering needs.
type Service interface {
// ExtractAll extracts tags, properties, and references in a single parse (most efficient)
ExtractAll(content []byte) (*ExtractedData, error)
// ExtractTags returns all #tags found in content
ExtractTags(content []byte) ([]string, error)
// ExtractProperties computes boolean properties
ExtractProperties(content []byte) (*storepb.MemoPayload_Property, error)
// RenderMarkdown renders goldmark AST back to markdown text
RenderMarkdown(content []byte) (string, error)
// RenderHTML renders markdown content to HTML
RenderHTML(content []byte) (string, error)
// GenerateSnippet creates plain text summary
GenerateSnippet(content []byte, maxLength int) (string, error)
// ValidateContent checks for syntax errors
ValidateContent(content []byte) error
// RenameTag renames all occurrences of oldTag to newTag in content
RenameTag(content []byte, oldTag, newTag string) (string, error)
}
// service implements the Service interface.
type service struct {
md goldmark.Markdown
}
// Option configures the markdown service.
type Option func(*config)
type config struct {
enableTags bool
}
// WithTagExtension enables #tag parsing.
func WithTagExtension() Option {
return func(c *config) {
c.enableTags = true
}
}
// NewService creates a new markdown service with the given options.
func NewService(opts ...Option) Service {
cfg := &config{}
for _, opt := range opts {
opt(cfg)
}
exts := []goldmark.Extender{
extension.GFM, // GitHub Flavored Markdown (tables, strikethrough, task lists, autolinks)
}
// Add custom extensions based on config
if cfg.enableTags {
exts = append(exts, extensions.TagExtension)
}
md := goldmark.New(
goldmark.WithExtensions(exts...),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(), // Generate heading IDs
),
)
return &service{
md: md,
}
}
// parse is an internal helper to parse content into AST.
func (s *service) parse(content []byte) (gast.Node, error) {
reader := text.NewReader(content)
doc := s.md.Parser().Parse(reader)
return doc, nil
}
// ExtractTags returns all #tags found in content.
func (s *service) ExtractTags(content []byte) ([]string, error) {
root, err := s.parse(content)
if err != nil {
return nil, err
}
var tags []string
// Walk the AST to find tag nodes
err = gast.Walk(root, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
if !entering {
return gast.WalkContinue, nil
}
// Check for custom TagNode
if tagNode, ok := n.(*mast.TagNode); ok {
tags = append(tags, string(tagNode.Tag))
}
return gast.WalkContinue, nil
})
if err != nil {
return nil, err
}
// Deduplicate tags while preserving original case
return uniquePreserveCase(tags), nil
}
// ExtractProperties computes boolean properties about the content.
func (s *service) ExtractProperties(content []byte) (*storepb.MemoPayload_Property, error) {
root, err := s.parse(content)
if err != nil {
return nil, err
}
prop := &storepb.MemoPayload_Property{}
err = gast.Walk(root, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
if !entering {
return gast.WalkContinue, nil
}
switch n.Kind() {
case gast.KindLink:
prop.HasLink = true
case gast.KindCodeBlock, gast.KindFencedCodeBlock, gast.KindCodeSpan:
prop.HasCode = true
case east.KindTaskCheckBox:
prop.HasTaskList = true
if checkBox, ok := n.(*east.TaskCheckBox); ok {
if !checkBox.IsChecked {
prop.HasIncompleteTasks = true
}
}
default:
// No special handling for other node types
}
return gast.WalkContinue, nil
})
if err != nil {
return nil, err
}
return prop, nil
}
// RenderMarkdown renders goldmark AST back to markdown text.
func (s *service) RenderMarkdown(content []byte) (string, error) {
root, err := s.parse(content)
if err != nil {
return "", err
}
mdRenderer := renderer.NewMarkdownRenderer()
return mdRenderer.Render(root, content), nil
}
// RenderHTML renders markdown content to HTML using goldmark's built-in HTML renderer.
func (s *service) RenderHTML(content []byte) (string, error) {
var buf bytes.Buffer
if err := s.md.Convert(content, &buf); err != nil {
return "", err
}
return buf.String(), nil
}
// GenerateSnippet creates a plain text summary from markdown content.
func (s *service) GenerateSnippet(content []byte, maxLength int) (string, error) {
root, err := s.parse(content)
if err != nil {
return "", err
}
var buf strings.Builder
var lastNodeWasBlock bool
err = gast.Walk(root, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
if entering {
// Skip code blocks and code spans entirely
switch n.Kind() {
case gast.KindCodeBlock, gast.KindFencedCodeBlock, gast.KindCodeSpan:
return gast.WalkSkipChildren, nil
default:
// Continue walking for other node types
}
// Add space before block elements (except first)
switch n.Kind() {
case gast.KindParagraph, gast.KindHeading, gast.KindListItem:
if buf.Len() > 0 && lastNodeWasBlock {
buf.WriteByte(' ')
}
default:
// No space needed for other node types
}
}
if !entering {
// Mark that we just exited a block element
switch n.Kind() {
case gast.KindParagraph, gast.KindHeading, gast.KindListItem:
lastNodeWasBlock = true
default:
// Not a block element
}
return gast.WalkContinue, nil
}
lastNodeWasBlock = false
// Only extract plain text nodes
if textNode, ok := n.(*gast.Text); ok {
segment := textNode.Segment
buf.Write(segment.Value(content))
// Add space if this is a soft line break
if textNode.SoftLineBreak() {
buf.WriteByte(' ')
}
}
// Stop walking if we've exceeded double the max length
// (we'll truncate precisely later)
if buf.Len() > maxLength*2 {
return gast.WalkStop, nil
}
return gast.WalkContinue, nil
})
if err != nil {
return "", err
}
snippet := buf.String()
// Truncate at word boundary if needed
if len(snippet) > maxLength {
snippet = truncateAtWord(snippet, maxLength)
}
return strings.TrimSpace(snippet), nil
}
// ValidateContent checks if the markdown content is valid.
func (s *service) ValidateContent(content []byte) error {
// Try to parse the content
_, err := s.parse(content)
return err
}
// ExtractAll extracts tags, properties, and references in a single parse for efficiency.
func (s *service) ExtractAll(content []byte) (*ExtractedData, error) {
root, err := s.parse(content)
if err != nil {
return nil, err
}
data := &ExtractedData{
Tags: []string{},
Property: &storepb.MemoPayload_Property{},
}
// Single walk to collect all data
err = gast.Walk(root, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
if !entering {
return gast.WalkContinue, nil
}
// Extract tags
if tagNode, ok := n.(*mast.TagNode); ok {
data.Tags = append(data.Tags, string(tagNode.Tag))
}
// Extract properties based on node kind
switch n.Kind() {
case gast.KindLink:
data.Property.HasLink = true
case gast.KindCodeBlock, gast.KindFencedCodeBlock, gast.KindCodeSpan:
data.Property.HasCode = true
case east.KindTaskCheckBox:
data.Property.HasTaskList = true
if checkBox, ok := n.(*east.TaskCheckBox); ok {
if !checkBox.IsChecked {
data.Property.HasIncompleteTasks = true
}
}
default:
// No special handling for other node types
}
return gast.WalkContinue, nil
})
if err != nil {
return nil, err
}
// Deduplicate tags while preserving original case
data.Tags = uniquePreserveCase(data.Tags)
return data, nil
}
// RenameTag renames all occurrences of oldTag to newTag in content.
func (s *service) RenameTag(content []byte, oldTag, newTag string) (string, error) {
root, err := s.parse(content)
if err != nil {
return "", err
}
// Walk the AST to find and rename tag nodes
err = gast.Walk(root, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
if !entering {
return gast.WalkContinue, nil
}
// Check for custom TagNode and rename if it matches
if tagNode, ok := n.(*mast.TagNode); ok {
if string(tagNode.Tag) == oldTag {
tagNode.Tag = []byte(newTag)
}
}
return gast.WalkContinue, nil
})
if err != nil {
return "", err
}
// Render back to markdown using the already-parsed AST
mdRenderer := renderer.NewMarkdownRenderer()
return mdRenderer.Render(root, content), nil
}
// uniquePreserveCase returns unique strings from input while preserving case.
func uniquePreserveCase(strs []string) []string {
seen := make(map[string]struct{})
var result []string
for _, s := range strs {
if _, exists := seen[s]; !exists {
seen[s] = struct{}{}
result = append(result, s)
}
}
return result
}
// truncateAtWord truncates a string at the last word boundary before maxLength.
// maxLength is treated as a rune (character) count to properly handle UTF-8 multi-byte characters.
func truncateAtWord(s string, maxLength int) string {
// Convert to runes to properly handle multi-byte UTF-8 characters
runes := []rune(s)
if len(runes) <= maxLength {
return s
}
// Truncate to max length (by character count, not byte count)
truncated := string(runes[:maxLength])
// Find last space to avoid cutting in the middle of a word
lastSpace := strings.LastIndexAny(truncated, " \t\n\r")
if lastSpace > 0 {
truncated = truncated[:lastSpace]
}
return truncated + " ..."
}
+448
View File
@@ -0,0 +1,448 @@
package markdown
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewService(t *testing.T) {
svc := NewService()
assert.NotNil(t, svc)
}
func TestValidateContent(t *testing.T) {
svc := NewService()
tests := []struct {
name string
content string
wantErr bool
}{
{
name: "valid markdown",
content: "# Hello\n\nThis is **bold** text.",
wantErr: false,
},
{
name: "empty content",
content: "",
wantErr: false,
},
{
name: "complex markdown",
content: "# Title\n\n- List item 1\n- List item 2\n\n```go\ncode block\n```",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := svc.ValidateContent([]byte(tt.content))
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestGenerateSnippet(t *testing.T) {
svc := NewService()
tests := []struct {
name string
content string
maxLength int
expected string
}{
{
name: "simple text",
content: "Hello world",
maxLength: 100,
expected: "Hello world",
},
{
name: "text with formatting",
content: "This is **bold** and *italic* text.",
maxLength: 100,
expected: "This is bold and italic text.",
},
{
name: "truncate long text",
content: "This is a very long piece of text that should be truncated at a word boundary.",
maxLength: 30,
expected: "This is a very long piece of ...",
},
{
name: "heading and paragraph",
content: "# My Title\n\nThis is the first paragraph.",
maxLength: 100,
expected: "My Title This is the first paragraph.",
},
{
name: "code block removed",
content: "Text before\n\n```go\ncode\n```\n\nText after",
maxLength: 100,
expected: "Text before Text after",
},
{
name: "list items",
content: "- Item 1\n- Item 2\n- Item 3",
maxLength: 100,
expected: "Item 1 Item 2 Item 3",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
snippet, err := svc.GenerateSnippet([]byte(tt.content), tt.maxLength)
require.NoError(t, err)
assert.Equal(t, tt.expected, snippet)
})
}
}
func TestExtractProperties(t *testing.T) {
tests := []struct {
name string
content string
hasLink bool
hasCode bool
hasTasks bool
hasInc bool
}{
{
name: "plain text",
content: "Just plain text",
hasLink: false,
hasCode: false,
hasTasks: false,
hasInc: false,
},
{
name: "with link",
content: "Check out [this link](https://example.com)",
hasLink: true,
hasCode: false,
hasTasks: false,
hasInc: false,
},
{
name: "with inline code",
content: "Use `console.log()` to debug",
hasLink: false,
hasCode: true,
hasTasks: false,
hasInc: false,
},
{
name: "with code block",
content: "```go\nfunc main() {}\n```",
hasLink: false,
hasCode: true,
hasTasks: false,
hasInc: false,
},
{
name: "with completed task",
content: "- [x] Completed task",
hasLink: false,
hasCode: false,
hasTasks: true,
hasInc: false,
},
{
name: "with incomplete task",
content: "- [ ] Todo item",
hasLink: false,
hasCode: false,
hasTasks: true,
hasInc: true,
},
{
name: "mixed tasks",
content: "- [x] Done\n- [ ] Not done",
hasLink: false,
hasCode: false,
hasTasks: true,
hasInc: true,
},
{
name: "everything",
content: "# Title\n\n[Link](url)\n\n`code`\n\n- [ ] Task",
hasLink: true,
hasCode: true,
hasTasks: true,
hasInc: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
svc := NewService()
props, err := svc.ExtractProperties([]byte(tt.content))
require.NoError(t, err)
assert.Equal(t, tt.hasLink, props.HasLink, "HasLink")
assert.Equal(t, tt.hasCode, props.HasCode, "HasCode")
assert.Equal(t, tt.hasTasks, props.HasTaskList, "HasTaskList")
assert.Equal(t, tt.hasInc, props.HasIncompleteTasks, "HasIncompleteTasks")
})
}
}
func TestExtractTags(t *testing.T) {
tests := []struct {
name string
content string
withExt bool
expected []string
}{
{
name: "no tags",
content: "Just plain text",
withExt: false,
expected: []string{},
},
{
name: "single tag",
content: "Text with #tag",
withExt: true,
expected: []string{"tag"},
},
{
name: "multiple tags",
content: "Text with #tag1 and #tag2",
withExt: true,
expected: []string{"tag1", "tag2"},
},
{
name: "duplicate tags",
content: "#work is important. #Work #WORK",
withExt: true,
expected: []string{"work", "Work", "WORK"},
},
{
name: "tags with hyphens and underscores",
content: "Tags: #work-notes #2024_plans",
withExt: true,
expected: []string{"work-notes", "2024_plans"},
},
{
name: "tags at end of sentence",
content: "This is important #urgent.",
withExt: true,
expected: []string{"urgent"},
},
{
name: "headings not tags",
content: "## Heading\n\n# Title\n\nText with #realtag",
withExt: true,
expected: []string{"realtag"},
},
{
name: "numeric tag",
content: "Issue #123",
withExt: true,
expected: []string{"123"},
},
{
name: "tag in list",
content: "- Item 1 #todo\n- Item 2 #done",
withExt: true,
expected: []string{"todo", "done"},
},
{
name: "no extension enabled",
content: "Text with #tag",
withExt: false,
expected: []string{},
},
{
name: "Chinese tag",
content: "Text with #测试",
withExt: true,
expected: []string{"测试"},
},
{
name: "Chinese tag followed by punctuation",
content: "Text #测试。 More text",
withExt: true,
expected: []string{"测试"},
},
{
name: "mixed Chinese and ASCII tag",
content: "#测试test123 content",
withExt: true,
expected: []string{"测试test123"},
},
{
name: "Japanese tag",
content: "#日本語 content",
withExt: true,
expected: []string{"日本語"},
},
{
name: "Korean tag",
content: "#한국어 content",
withExt: true,
expected: []string{"한국어"},
},
{
name: "hierarchical tag with Chinese",
content: "#work/测试/项目",
withExt: true,
expected: []string{"work/测试/项目"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var svc Service
if tt.withExt {
svc = NewService(WithTagExtension())
} else {
svc = NewService()
}
tags, err := svc.ExtractTags([]byte(tt.content))
require.NoError(t, err)
assert.ElementsMatch(t, tt.expected, tags)
})
}
}
func TestUniquePreserveCase(t *testing.T) {
tests := []struct {
name string
input []string
expected []string
}{
{
name: "empty",
input: []string{},
expected: []string{},
},
{
name: "unique items",
input: []string{"tag1", "tag2", "tag3"},
expected: []string{"tag1", "tag2", "tag3"},
},
{
name: "duplicates",
input: []string{"tag", "TAG", "Tag"},
expected: []string{"tag", "TAG", "Tag"},
},
{
name: "mixed",
input: []string{"Work", "work", "Important", "work"},
expected: []string{"Work", "work", "Important"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := uniquePreserveCase(tt.input)
assert.ElementsMatch(t, tt.expected, result)
})
}
}
func TestTruncateAtWord(t *testing.T) {
tests := []struct {
name string
input string
maxLength int
expected string
}{
{
name: "no truncation needed",
input: "short",
maxLength: 10,
expected: "short",
},
{
name: "exact length",
input: "exactly ten",
maxLength: 11,
expected: "exactly ten",
},
{
name: "truncate at word",
input: "this is a long sentence",
maxLength: 10,
expected: "this is a ...",
},
{
name: "truncate very long word",
input: "supercalifragilisticexpialidocious",
maxLength: 10,
expected: "supercalif ...",
},
{
name: "CJK characters without spaces",
input: "这是一个很长的中文句子没有空格的情况下也要正确处理",
maxLength: 15,
expected: "这是一个很长的中文句子没有空格 ...",
},
{
name: "mixed CJK and Latin",
input: "这是中文mixed with English文字",
maxLength: 10,
expected: "这是中文mixed ...",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := truncateAtWord(tt.input, tt.maxLength)
assert.Equal(t, tt.expected, result)
})
}
}
// Benchmark tests.
func BenchmarkGenerateSnippet(b *testing.B) {
svc := NewService()
content := []byte(`# Large Document
This is a large document with multiple paragraphs and formatting.
## Section 1
Here is some **bold** text and *italic* text with [links](https://example.com).
- List item 1
- List item 2
- List item 3
## Section 2
More content here with ` + "`inline code`" + ` and other elements.
` + "```go\nfunc example() {\n return true\n}\n```")
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := svc.GenerateSnippet(content, 200)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkExtractProperties(b *testing.B) {
svc := NewService()
content := []byte("# Title\n\n[Link](url)\n\n`code`\n\n- [ ] Task\n- [x] Done")
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := svc.ExtractProperties(content)
if err != nil {
b.Fatal(err)
}
}
}
+139
View File
@@ -0,0 +1,139 @@
package parser
import (
"unicode"
"unicode/utf8"
gast "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
mast "github.com/usememos/memos/plugin/markdown/ast"
)
const (
// MaxTagLength defines the maximum number of runes allowed in a tag.
MaxTagLength = 100
)
type tagParser struct{}
// NewTagParser creates a new inline parser for #tag syntax.
func NewTagParser() parser.InlineParser {
return &tagParser{}
}
// Trigger returns the characters that trigger this parser.
func (*tagParser) Trigger() []byte {
return []byte{'#'}
}
// isValidTagRune checks if a Unicode rune is valid in a tag.
// Uses Unicode categories for proper international character support.
func isValidTagRune(r rune) bool {
// Allow Unicode letters (any script: Latin, CJK, Arabic, Cyrillic, etc.)
if unicode.IsLetter(r) {
return true
}
// Allow Unicode digits
if unicode.IsNumber(r) {
return true
}
// Allow emoji and symbols (So category: Symbol, Other)
// This includes emoji, which are essential for social media-style tagging
if unicode.IsSymbol(r) {
return true
}
// Allow specific ASCII symbols for tag structure
// Underscore: word separation (snake_case)
// Hyphen: word separation (kebab-case)
// Forward slash: hierarchical tags (category/subcategory)
// Ampersand: compound tags (science&tech)
if r == '_' || r == '-' || r == '/' || r == '&' {
return true
}
return false
}
// Parse parses #tag syntax using Unicode-aware validation.
// Tags support international characters and follow these rules:
// - Must start with # followed by valid tag characters
// - Valid characters: Unicode letters, Unicode digits, underscore (_), hyphen (-), forward slash (/)
// - Maximum length: 100 runes (Unicode characters)
// - Stops at: whitespace, punctuation, or other invalid characters
func (*tagParser) Parse(_ gast.Node, block text.Reader, _ parser.Context) gast.Node {
line, _ := block.PeekLine()
// Must start with #
if len(line) == 0 || line[0] != '#' {
return nil
}
// Check if it's a heading (## or space after #)
if len(line) > 1 {
if line[1] == '#' {
// It's a heading (##), not a tag
return nil
}
if line[1] == ' ' {
// Space after # - heading or just a hash
return nil
}
} else {
// Just a lone #
return nil
}
// Parse tag using UTF-8 aware rune iteration
tagStart := 1
pos := tagStart
runeCount := 0
for pos < len(line) {
r, size := utf8.DecodeRune(line[pos:])
// Stop at invalid UTF-8
if r == utf8.RuneError && size == 1 {
break
}
// Validate character using Unicode categories
if !isValidTagRune(r) {
break
}
// Enforce max length (by rune count, not byte count)
runeCount++
if runeCount > MaxTagLength {
break
}
pos += size
}
// Must have at least one character after #
if pos <= tagStart {
return nil
}
// Extract tag (without #)
tagName := line[tagStart:pos]
// Make a copy of the tag name
tagCopy := make([]byte, len(tagName))
copy(tagCopy, tagName)
// Advance reader
block.Advance(pos)
// Create node
node := &mast.TagNode{
Tag: tagCopy,
}
return node
}
+251
View File
@@ -0,0 +1,251 @@
package parser
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
mast "github.com/usememos/memos/plugin/markdown/ast"
)
func TestTagParser(t *testing.T) {
tests := []struct {
name string
input string
expectedTag string
shouldParse bool
}{
{
name: "basic tag",
input: "#tag",
expectedTag: "tag",
shouldParse: true,
},
{
name: "tag with hyphen",
input: "#work-notes",
expectedTag: "work-notes",
shouldParse: true,
},
{
name: "tag with ampersand",
input: "#science&tech",
expectedTag: "science&tech",
shouldParse: true,
},
{
name: "tag with underscore",
input: "#2024_plans",
expectedTag: "2024_plans",
shouldParse: true,
},
{
name: "numeric tag",
input: "#123",
expectedTag: "123",
shouldParse: true,
},
{
name: "tag followed by space",
input: "#tag ",
expectedTag: "tag",
shouldParse: true,
},
{
name: "tag followed by punctuation",
input: "#tag.",
expectedTag: "tag",
shouldParse: true,
},
{
name: "tag in sentence",
input: "#important task",
expectedTag: "important",
shouldParse: true,
},
{
name: "heading (##)",
input: "## Heading",
expectedTag: "",
shouldParse: false,
},
{
name: "space after hash",
input: "# heading",
expectedTag: "",
shouldParse: false,
},
{
name: "lone hash",
input: "#",
expectedTag: "",
shouldParse: false,
},
{
name: "hash with space",
input: "# ",
expectedTag: "",
shouldParse: false,
},
{
name: "special characters",
input: "#tag@special",
expectedTag: "tag",
shouldParse: true,
},
{
name: "mixed case",
input: "#WorkNotes",
expectedTag: "WorkNotes",
shouldParse: true,
},
{
name: "hierarchical tag with slash",
input: "#tag1/subtag",
expectedTag: "tag1/subtag",
shouldParse: true,
},
{
name: "hierarchical tag with multiple levels",
input: "#tag1/subtag/subtag2",
expectedTag: "tag1/subtag/subtag2",
shouldParse: true,
},
{
name: "hierarchical tag followed by space",
input: "#work/notes ",
expectedTag: "work/notes",
shouldParse: true,
},
{
name: "hierarchical tag followed by punctuation",
input: "#project/2024.",
expectedTag: "project/2024",
shouldParse: true,
},
{
name: "hierarchical tag with numbers and dashes",
input: "#work-log/2024/q1",
expectedTag: "work-log/2024/q1",
shouldParse: true,
},
{
name: "Chinese characters",
input: "#测试",
expectedTag: "测试",
shouldParse: true,
},
{
name: "Chinese tag followed by space",
input: "#测试 some text",
expectedTag: "测试",
shouldParse: true,
},
{
name: "Chinese tag followed by punctuation",
input: "#测试。",
expectedTag: "测试",
shouldParse: true,
},
{
name: "mixed Chinese and ASCII",
input: "#测试test123",
expectedTag: "测试test123",
shouldParse: true,
},
{
name: "Japanese characters",
input: "#テスト",
expectedTag: "テスト",
shouldParse: true,
},
{
name: "Korean characters",
input: "#테스트",
expectedTag: "테스트",
shouldParse: true,
},
{
name: "emoji",
input: "#test🚀",
expectedTag: "test🚀",
shouldParse: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := NewTagParser()
reader := text.NewReader([]byte(tt.input))
ctx := parser.NewContext()
node := p.Parse(nil, reader, ctx)
if tt.shouldParse {
require.NotNil(t, node, "Expected tag to be parsed")
require.IsType(t, &mast.TagNode{}, node)
tagNode, ok := node.(*mast.TagNode)
require.True(t, ok, "Expected node to be *mast.TagNode")
assert.Equal(t, tt.expectedTag, string(tagNode.Tag))
} else {
assert.Nil(t, node, "Expected tag NOT to be parsed")
}
})
}
}
func TestTagParser_Trigger(t *testing.T) {
p := NewTagParser()
triggers := p.Trigger()
assert.Equal(t, []byte{'#'}, triggers)
}
func TestTagParser_MultipleTags(t *testing.T) {
// Test that parser correctly handles multiple tags in sequence
input := "#tag1 #tag2"
p := NewTagParser()
reader := text.NewReader([]byte(input))
ctx := parser.NewContext()
// Parse first tag
node1 := p.Parse(nil, reader, ctx)
require.NotNil(t, node1)
tagNode1, ok := node1.(*mast.TagNode)
require.True(t, ok, "Expected node1 to be *mast.TagNode")
assert.Equal(t, "tag1", string(tagNode1.Tag))
// Advance past the space
reader.Advance(1)
// Parse second tag
node2 := p.Parse(nil, reader, ctx)
require.NotNil(t, node2)
tagNode2, ok := node2.(*mast.TagNode)
require.True(t, ok, "Expected node2 to be *mast.TagNode")
assert.Equal(t, "tag2", string(tagNode2.Tag))
}
func TestTagNode_Kind(t *testing.T) {
node := &mast.TagNode{
Tag: []byte("test"),
}
assert.Equal(t, mast.KindTag, node.Kind())
}
func TestTagNode_Dump(t *testing.T) {
node := &mast.TagNode{
Tag: []byte("test"),
}
// Should not panic
assert.NotPanics(t, func() {
node.Dump([]byte("#test"), 0)
})
}
@@ -0,0 +1,266 @@
package renderer
import (
"bytes"
"fmt"
"strings"
gast "github.com/yuin/goldmark/ast"
east "github.com/yuin/goldmark/extension/ast"
mast "github.com/usememos/memos/plugin/markdown/ast"
)
// MarkdownRenderer renders goldmark AST back to markdown text.
type MarkdownRenderer struct {
buf *bytes.Buffer
}
// NewMarkdownRenderer creates a new markdown renderer.
func NewMarkdownRenderer() *MarkdownRenderer {
return &MarkdownRenderer{
buf: &bytes.Buffer{},
}
}
// Render renders the AST node to markdown and returns the result.
func (r *MarkdownRenderer) Render(node gast.Node, source []byte) string {
r.buf.Reset()
r.renderNode(node, source, 0)
return r.buf.String()
}
// renderNode renders a single node and its children.
func (r *MarkdownRenderer) renderNode(node gast.Node, source []byte, depth int) {
switch n := node.(type) {
case *gast.Document:
r.renderChildren(n, source, depth)
case *gast.Paragraph:
r.renderChildren(n, source, depth)
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
case *gast.Text:
// Text nodes store their content as segments in the source
segment := n.Segment
r.buf.Write(segment.Value(source))
if n.SoftLineBreak() {
r.buf.WriteByte('\n')
} else if n.HardLineBreak() {
r.buf.WriteString(" \n")
}
case *gast.CodeSpan:
r.buf.WriteByte('`')
r.renderChildren(n, source, depth)
r.buf.WriteByte('`')
case *gast.Emphasis:
symbol := "*"
if n.Level == 2 {
symbol = "**"
}
r.buf.WriteString(symbol)
r.renderChildren(n, source, depth)
r.buf.WriteString(symbol)
case *gast.Link:
r.buf.WriteString("[")
r.renderChildren(n, source, depth)
r.buf.WriteString("](")
r.buf.Write(n.Destination)
if len(n.Title) > 0 {
r.buf.WriteString(` "`)
r.buf.Write(n.Title)
r.buf.WriteString(`"`)
}
r.buf.WriteString(")")
case *gast.AutoLink:
url := n.URL(source)
if n.AutoLinkType == gast.AutoLinkEmail {
r.buf.WriteString("<")
r.buf.Write(url)
r.buf.WriteString(">")
} else {
r.buf.Write(url)
}
case *gast.Image:
r.buf.WriteString("![")
r.renderChildren(n, source, depth)
r.buf.WriteString("](")
r.buf.Write(n.Destination)
if len(n.Title) > 0 {
r.buf.WriteString(` "`)
r.buf.Write(n.Title)
r.buf.WriteString(`"`)
}
r.buf.WriteString(")")
case *gast.Heading:
r.buf.WriteString(strings.Repeat("#", n.Level))
r.buf.WriteByte(' ')
r.renderChildren(n, source, depth)
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
case *gast.CodeBlock, *gast.FencedCodeBlock:
r.renderCodeBlock(n, source)
case *gast.Blockquote:
// Render each child line with "> " prefix
r.renderBlockquote(n, source, depth)
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
case *gast.List:
r.renderChildren(n, source, depth)
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
case *gast.ListItem:
r.renderListItem(n, source, depth)
case *gast.ThematicBreak:
r.buf.WriteString("---")
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
case *east.Strikethrough:
r.buf.WriteString("~~")
r.renderChildren(n, source, depth)
r.buf.WriteString("~~")
case *east.TaskCheckBox:
if n.IsChecked {
r.buf.WriteString("[x] ")
} else {
r.buf.WriteString("[ ] ")
}
case *east.Table:
r.renderTable(n, source)
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
// Custom Memos nodes
case *mast.TagNode:
r.buf.WriteByte('#')
r.buf.Write(n.Tag)
default:
// For unknown nodes, try to render children
r.renderChildren(n, source, depth)
}
}
// renderChildren renders all children of a node.
func (r *MarkdownRenderer) renderChildren(node gast.Node, source []byte, depth int) {
child := node.FirstChild()
for child != nil {
r.renderNode(child, source, depth+1)
child = child.NextSibling()
}
}
// renderCodeBlock renders a code block.
func (r *MarkdownRenderer) renderCodeBlock(node gast.Node, source []byte) {
if fenced, ok := node.(*gast.FencedCodeBlock); ok {
// Fenced code block with language
r.buf.WriteString("```")
if lang := fenced.Language(source); len(lang) > 0 {
r.buf.Write(lang)
}
r.buf.WriteByte('\n')
// Write all lines
lines := fenced.Lines()
for i := 0; i < lines.Len(); i++ {
line := lines.At(i)
r.buf.Write(line.Value(source))
}
r.buf.WriteString("```")
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
} else if codeBlock, ok := node.(*gast.CodeBlock); ok {
// Indented code block
lines := codeBlock.Lines()
for i := 0; i < lines.Len(); i++ {
line := lines.At(i)
r.buf.WriteString(" ")
r.buf.Write(line.Value(source))
}
if node.NextSibling() != nil {
r.buf.WriteString("\n\n")
}
}
}
// renderBlockquote renders a blockquote with "> " prefix.
func (r *MarkdownRenderer) renderBlockquote(node *gast.Blockquote, source []byte, depth int) {
// Create a temporary buffer for the blockquote content
tempBuf := &bytes.Buffer{}
tempRenderer := &MarkdownRenderer{buf: tempBuf}
tempRenderer.renderChildren(node, source, depth)
// Add "> " prefix to each line
content := tempBuf.String()
lines := strings.Split(strings.TrimRight(content, "\n"), "\n")
for i, line := range lines {
r.buf.WriteString("> ")
r.buf.WriteString(line)
if i < len(lines)-1 {
r.buf.WriteByte('\n')
}
}
}
// renderListItem renders a list item with proper indentation and markers.
func (r *MarkdownRenderer) renderListItem(node *gast.ListItem, source []byte, depth int) {
parent := node.Parent()
list, ok := parent.(*gast.List)
if !ok {
r.renderChildren(node, source, depth)
return
}
// Add indentation only for nested lists
// Document=0, List=1, ListItem=2 (no indent), nested ListItem=3+ (indent)
if depth > 2 {
indent := strings.Repeat(" ", depth-2)
r.buf.WriteString(indent)
}
// Add list marker
if list.IsOrdered() {
fmt.Fprintf(r.buf, "%d. ", list.Start)
list.Start++ // Increment for next item
} else {
r.buf.WriteString("- ")
}
// Render content
r.renderChildren(node, source, depth)
// Add newline if there's a next sibling
if node.NextSibling() != nil {
r.buf.WriteByte('\n')
}
}
// renderTable renders a table in markdown format.
func (r *MarkdownRenderer) renderTable(table *east.Table, source []byte) {
// This is a simplified table renderer
// A full implementation would need to handle alignment, etc.
r.renderChildren(table, source, 0)
}
@@ -0,0 +1,176 @@
package renderer
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
"github.com/usememos/memos/plugin/markdown/extensions"
)
func TestMarkdownRenderer(t *testing.T) {
// Create goldmark instance with all extensions
md := goldmark.New(
goldmark.WithExtensions(
extension.GFM,
extensions.TagExtension,
),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
)
tests := []struct {
name string
input string
expected string
}{
{
name: "simple text",
input: "Hello world",
expected: "Hello world",
},
{
name: "paragraph with newlines",
input: "First paragraph\n\nSecond paragraph",
expected: "First paragraph\n\nSecond paragraph",
},
{
name: "emphasis",
input: "This is *italic* and **bold** text",
expected: "This is *italic* and **bold** text",
},
{
name: "headings",
input: "# Heading 1\n\n## Heading 2\n\n### Heading 3",
expected: "# Heading 1\n\n## Heading 2\n\n### Heading 3",
},
{
name: "link",
input: "Check [this link](https://example.com)",
expected: "Check [this link](https://example.com)",
},
{
name: "image",
input: "![alt text](image.png)",
expected: "![alt text](image.png)",
},
{
name: "code inline",
input: "This is `inline code` here",
expected: "This is `inline code` here",
},
{
name: "code block fenced",
input: "```go\nfunc main() {\n}\n```",
expected: "```go\nfunc main() {\n}\n```",
},
{
name: "unordered list",
input: "- Item 1\n- Item 2\n- Item 3",
expected: "- Item 1\n- Item 2\n- Item 3",
},
{
name: "ordered list",
input: "1. First\n2. Second\n3. Third",
expected: "1. First\n2. Second\n3. Third",
},
{
name: "blockquote",
input: "> This is a quote\n> Second line",
expected: "> This is a quote\n> Second line",
},
{
name: "horizontal rule",
input: "Text before\n\n---\n\nText after",
expected: "Text before\n\n---\n\nText after",
},
{
name: "strikethrough",
input: "This is ~~deleted~~ text",
expected: "This is ~~deleted~~ text",
},
{
name: "task list",
input: "- [x] Completed task\n- [ ] Incomplete task",
expected: "- [x] Completed task\n- [ ] Incomplete task",
},
{
name: "tag",
input: "This has #tag in it",
expected: "This has #tag in it",
},
{
name: "multiple tags",
input: "#work #important meeting notes",
expected: "#work #important meeting notes",
},
{
name: "complex mixed content",
input: "# Meeting Notes\n\n**Date**: 2024-01-01\n\n## Attendees\n- Alice\n- Bob\n\n## Discussion\n\nWe discussed #project status.\n\n```python\nprint('hello')\n```",
expected: "# Meeting Notes\n\n**Date**: 2024-01-01\n\n## Attendees\n\n- Alice\n- Bob\n\n## Discussion\n\nWe discussed #project status.\n\n```python\nprint('hello')\n```",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Parse the input
source := []byte(tt.input)
reader := text.NewReader(source)
doc := md.Parser().Parse(reader)
require.NotNil(t, doc)
// Render back to markdown
renderer := NewMarkdownRenderer()
result := renderer.Render(doc, source)
// For debugging
if result != tt.expected {
t.Logf("Input: %q", tt.input)
t.Logf("Expected: %q", tt.expected)
t.Logf("Got: %q", result)
}
assert.Equal(t, tt.expected, result)
})
}
}
func TestMarkdownRendererPreservesStructure(t *testing.T) {
// Test that parsing and rendering preserves structure
md := goldmark.New(
goldmark.WithExtensions(
extension.GFM,
extensions.TagExtension,
),
)
inputs := []string{
"# Title\n\nParagraph",
"**Bold** and *italic*",
"- List\n- Items",
"#tag #another",
"> Quote",
}
renderer := NewMarkdownRenderer()
for _, input := range inputs {
t.Run(input, func(t *testing.T) {
source := []byte(input)
reader := text.NewReader(source)
doc := md.Parser().Parse(reader)
result := renderer.Render(doc, source)
// The result should be structurally similar
// (may have minor formatting differences)
assert.NotEmpty(t, result)
})
}
}
+367
View File
@@ -0,0 +1,367 @@
# Scheduler Plugin
A production-ready, GitHub Actions-inspired cron job scheduler for Go.
## Features
- **Standard Cron Syntax**: Supports both 5-field and 6-field (with seconds) cron expressions
- **Timezone-Aware**: Explicit timezone handling to avoid DST surprises
- **Middleware Pattern**: Composable job wrappers for logging, metrics, panic recovery, timeouts
- **Graceful Shutdown**: Jobs complete cleanly or cancel when context expires
- **Zero Dependencies**: Core functionality uses only the standard library
- **Type-Safe**: Strong typing with clear error messages
- **Well-Tested**: Comprehensive test coverage
## Installation
This package is included with Memos. No separate installation required.
## Quick Start
```go
package main
import (
"context"
"fmt"
"github.com/usememos/memos/plugin/scheduler"
)
func main() {
s := scheduler.New()
s.Register(&scheduler.Job{
Name: "daily-cleanup",
Schedule: "0 2 * * *", // 2 AM daily
Handler: func(ctx context.Context) error {
fmt.Println("Running cleanup...")
return nil
},
})
s.Start()
defer s.Stop(context.Background())
// Keep running...
select {}
}
```
## Cron Expression Format
### 5-Field Format (Standard)
```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 7) (Sunday = 0 or 7)
│ │ │ │ │
* * * * *
```
### 6-Field Format (With Seconds)
```
┌───────────── second (0 - 59)
│ ┌───────────── minute (0 - 59)
│ │ ┌───────────── hour (0 - 23)
│ │ │ ┌───────────── day of month (1 - 31)
│ │ │ │ ┌───────────── month (1 - 12)
│ │ │ │ │ ┌───────────── day of week (0 - 7)
│ │ │ │ │ │
* * * * * *
```
### Special Characters
- `*` - Any value (every minute, every hour, etc.)
- `,` - List of values: `1,15,30` (1st, 15th, and 30th)
- `-` - Range: `9-17` (9 AM through 5 PM)
- `/` - Step: `*/15` (every 15 units)
### Common Examples
| Schedule | Description |
|----------|-------------|
| `* * * * *` | Every minute |
| `0 * * * *` | Every hour |
| `0 0 * * *` | Daily at midnight |
| `0 9 * * 1-5` | Weekdays at 9 AM |
| `*/15 * * * *` | Every 15 minutes |
| `0 0 1 * *` | First day of every month |
| `0 0 * * 0` | Every Sunday at midnight |
| `30 14 * * *` | Every day at 2:30 PM |
## Timezone Support
```go
// Global timezone for all jobs
s := scheduler.New(
scheduler.WithTimezone("America/New_York"),
)
// Per-job timezone (overrides global)
s.Register(&scheduler.Job{
Name: "tokyo-report",
Schedule: "0 9 * * *", // 9 AM Tokyo time
Timezone: "Asia/Tokyo",
Handler: func(ctx context.Context) error {
// Runs at 9 AM in Tokyo
return nil
},
})
```
**Important**: Always use IANA timezone names (`America/New_York`, not `EST`).
## Middleware
Middleware wraps job handlers to add cross-cutting behavior. Multiple middleware can be chained together.
### Built-in Middleware
#### Recovery (Panic Handling)
```go
s := scheduler.New(
scheduler.WithMiddleware(
scheduler.Recovery(func(jobName string, r interface{}) {
log.Printf("Job %s panicked: %v", jobName, r)
}),
),
)
```
#### Logging
```go
type Logger interface {
Info(msg string, args ...interface{})
Error(msg string, args ...interface{})
}
s := scheduler.New(
scheduler.WithMiddleware(
scheduler.Logging(myLogger),
),
)
```
#### Timeout
```go
s := scheduler.New(
scheduler.WithMiddleware(
scheduler.Timeout(5 * time.Minute),
),
)
```
### Combining Middleware
```go
s := scheduler.New(
scheduler.WithMiddleware(
scheduler.Recovery(panicHandler),
scheduler.Logging(logger),
scheduler.Timeout(10 * time.Minute),
),
)
```
**Order matters**: Middleware are applied left-to-right. In the example above:
1. Recovery (outermost) catches panics from everything
2. Logging logs the execution
3. Timeout (innermost) wraps the actual handler
### Custom Middleware
```go
func Metrics(recorder MetricsRecorder) scheduler.Middleware {
return func(next scheduler.JobHandler) scheduler.JobHandler {
return func(ctx context.Context) error {
start := time.Now()
err := next(ctx)
duration := time.Since(start)
jobName := scheduler.GetJobName(ctx)
recorder.Record(jobName, duration, err)
return err
}
}
}
```
## Graceful Shutdown
Always use `Stop()` with a context to allow jobs to finish cleanly:
```go
// Give jobs up to 30 seconds to complete
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := s.Stop(ctx); err != nil {
log.Printf("Shutdown error: %v", err)
}
```
Jobs should respect context cancellation:
```go
Handler: func(ctx context.Context) error {
for i := 0; i < 100; i++ {
select {
case <-ctx.Done():
return ctx.Err() // Canceled
default:
// Do work
}
}
return nil
}
```
## Best Practices
### 1. Always Name Your Jobs
Names are used for logging, metrics, and debugging:
```go
Name: "user-cleanup-job" // Good
Name: "job1" // Bad
```
### 2. Add Descriptions and Tags
```go
s.Register(&scheduler.Job{
Name: "stale-session-cleanup",
Description: "Removes user sessions older than 30 days",
Tags: []string{"maintenance", "security"},
Schedule: "0 3 * * *",
Handler: cleanupSessions,
})
```
### 3. Use Appropriate Middleware
Always include Recovery and Logging in production:
```go
scheduler.New(
scheduler.WithMiddleware(
scheduler.Recovery(logPanic),
scheduler.Logging(logger),
),
)
```
### 4. Avoid Scheduling Exactly on the Hour
Many systems schedule jobs at `:00`, causing load spikes. Stagger your jobs:
```go
"5 2 * * *" // 2:05 AM (good)
"0 2 * * *" // 2:00 AM (often overloaded)
```
### 5. Make Jobs Idempotent
Jobs may run multiple times (crash recovery, etc.). Design them to be safely re-runnable:
```go
Handler: func(ctx context.Context) error {
// Use unique constraint or check-before-insert
db.Exec("INSERT IGNORE INTO processed_items ...")
return nil
}
```
### 6. Handle Timezones Explicitly
Always specify timezone for business-hour jobs:
```go
Timezone: "America/New_York" // Good
// Timezone: "" // Bad (defaults to UTC)
```
### 7. Test Your Cron Expressions
Use a cron expression calculator before deploying:
- [crontab.guru](https://crontab.guru/)
- Write unit tests with the parser
## Testing Jobs
Test job handlers independently of the scheduler:
```go
func TestCleanupJob(t *testing.T) {
ctx := context.Background()
err := cleanupHandler(ctx)
if err != nil {
t.Fatalf("cleanup failed: %v", err)
}
// Verify cleanup occurred
}
```
Test schedule parsing:
```go
func TestScheduleParsing(t *testing.T) {
job := &scheduler.Job{
Name: "test",
Schedule: "0 2 * * *",
Handler: func(ctx context.Context) error { return nil },
}
if err := job.Validate(); err != nil {
t.Fatalf("invalid job: %v", err)
}
}
```
## Comparison to Other Solutions
| Feature | scheduler | robfig/cron | github.com/go-co-op/gocron |
|---------|-----------|-------------|----------------------------|
| Standard cron syntax | ✅ | ✅ | ✅ |
| Seconds support | ✅ | ✅ | ✅ |
| Timezone support | ✅ | ✅ | ✅ |
| Middleware pattern | ✅ | ⚠️ (basic) | ❌ |
| Graceful shutdown | ✅ | ⚠️ (basic) | ✅ |
| Zero dependencies | ✅ | ❌ | ❌ |
| Job metadata | ✅ | ❌ | ⚠️ (limited) |
## API Reference
See [example_test.go](./example_test.go) for comprehensive examples.
### Core Types
- `Scheduler` - Manages scheduled jobs
- `Job` - Job definition with schedule and handler
- `Middleware` - Function that wraps job handlers
### Functions
- `New(opts ...Option) *Scheduler` - Create new scheduler
- `WithTimezone(tz string) Option` - Set default timezone
- `WithMiddleware(mw ...Middleware) Option` - Add middleware
### Methods
- `Register(job *Job) error` - Add job to scheduler
- `Start() error` - Begin executing jobs
- `Stop(ctx context.Context) error` - Graceful shutdown
## License
This package is part of the Memos project and shares its license.
+35
View File
@@ -0,0 +1,35 @@
// Package scheduler provides a GitHub Actions-inspired cron job scheduler.
//
// Features:
// - Standard cron expression syntax (5-field and 6-field formats)
// - Timezone-aware scheduling
// - Middleware pattern for cross-cutting concerns (logging, metrics, recovery)
// - Graceful shutdown with context cancellation
// - Zero external dependencies
//
// Basic usage:
//
// s := scheduler.New()
//
// s.Register(&scheduler.Job{
// Name: "daily-cleanup",
// Schedule: "0 2 * * *", // 2 AM daily
// Handler: func(ctx context.Context) error {
// // Your cleanup logic here
// return nil
// },
// })
//
// s.Start()
// defer s.Stop(context.Background())
//
// With middleware:
//
// s := scheduler.New(
// scheduler.WithTimezone("America/New_York"),
// scheduler.WithMiddleware(
// scheduler.Recovery(),
// scheduler.Logging(),
// ),
// )
package scheduler
+165
View File
@@ -0,0 +1,165 @@
package scheduler_test
import (
"context"
"fmt"
"log/slog"
"os"
"time"
"github.com/usememos/memos/plugin/scheduler"
)
// Example demonstrates basic scheduler usage.
func Example_basic() {
s := scheduler.New()
s.Register(&scheduler.Job{
Name: "hello",
Schedule: "*/5 * * * *", // Every 5 minutes
Description: "Say hello",
Handler: func(_ context.Context) error {
fmt.Println("Hello from scheduler!")
return nil
},
})
s.Start()
defer s.Stop(context.Background())
// Scheduler runs in background
time.Sleep(100 * time.Millisecond)
}
// Example demonstrates timezone-aware scheduling.
func Example_timezone() {
s := scheduler.New(
scheduler.WithTimezone("America/New_York"),
)
s.Register(&scheduler.Job{
Name: "daily-report",
Schedule: "0 9 * * *", // 9 AM in New York
Handler: func(_ context.Context) error {
fmt.Println("Generating daily report...")
return nil
},
})
s.Start()
defer s.Stop(context.Background())
}
// Example demonstrates middleware usage.
func Example_middleware() {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
s := scheduler.New(
scheduler.WithMiddleware(
scheduler.Recovery(func(jobName string, r interface{}) {
logger.Error("Job panicked", "job", jobName, "panic", r)
}),
scheduler.Logging(&slogAdapter{logger}),
scheduler.Timeout(5*time.Minute),
),
)
s.Register(&scheduler.Job{
Name: "data-sync",
Schedule: "0 */2 * * *", // Every 2 hours
Handler: func(_ context.Context) error {
// Your sync logic here
return nil
},
})
s.Start()
defer s.Stop(context.Background())
}
// slogAdapter adapts slog.Logger to scheduler.Logger interface.
type slogAdapter struct {
logger *slog.Logger
}
func (a *slogAdapter) Info(msg string, args ...interface{}) {
a.logger.Info(msg, args...)
}
func (a *slogAdapter) Error(msg string, args ...interface{}) {
a.logger.Error(msg, args...)
}
// Example demonstrates multiple jobs with different schedules.
func Example_multipleJobs() {
s := scheduler.New()
// Cleanup old data every night at 2 AM
s.Register(&scheduler.Job{
Name: "cleanup",
Schedule: "0 2 * * *",
Tags: []string{"maintenance"},
Handler: func(_ context.Context) error {
fmt.Println("Cleaning up old data...")
return nil
},
})
// Health check every 5 minutes
s.Register(&scheduler.Job{
Name: "health-check",
Schedule: "*/5 * * * *",
Tags: []string{"monitoring"},
Handler: func(_ context.Context) error {
fmt.Println("Running health check...")
return nil
},
})
// Weekly backup on Sundays at 1 AM
s.Register(&scheduler.Job{
Name: "weekly-backup",
Schedule: "0 1 * * 0",
Tags: []string{"backup"},
Handler: func(_ context.Context) error {
fmt.Println("Creating weekly backup...")
return nil
},
})
s.Start()
defer s.Stop(context.Background())
}
// Example demonstrates graceful shutdown with timeout.
func Example_gracefulShutdown() {
s := scheduler.New()
s.Register(&scheduler.Job{
Name: "long-running",
Schedule: "* * * * *",
Handler: func(ctx context.Context) error {
select {
case <-time.After(30 * time.Second):
fmt.Println("Job completed")
case <-ctx.Done():
fmt.Println("Job canceled, cleaning up...")
return ctx.Err()
}
return nil
},
})
s.Start()
// Simulate shutdown signal
time.Sleep(5 * time.Second)
// Give jobs 10 seconds to finish
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := s.Stop(shutdownCtx); err != nil {
fmt.Printf("Shutdown error: %v\n", err)
}
}

Some files were not shown because too many files have changed in this diff Show More