@symbiosis-lab/moss-plugin-matters 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -0
- package/README.md +18 -0
- package/assets/icon.svg +1 -0
- package/assets/manifest.json +36 -0
- package/codegen.ts +26 -0
- package/e2e/moss-cli.test.ts +338 -0
- package/features/api/fetch-articles.feature +39 -0
- package/features/auth/wallet-auth.feature +27 -0
- package/features/download/retry-logic.feature +36 -0
- package/features/download/self-correcting.feature +83 -0
- package/features/download/worker-pool.feature +29 -0
- package/features/social/fetch-social-data.feature +40 -0
- package/features/steps/api.steps.ts +180 -0
- package/features/steps/download.steps.ts +423 -0
- package/features/steps/incremental-sync.steps.ts +105 -0
- package/features/steps/self-correcting.steps.ts +575 -0
- package/features/steps/social.steps.ts +257 -0
- package/features/steps/syndication.steps.ts +264 -0
- package/features/steps/wallet-auth.steps.ts +185 -0
- package/features/sync/article-sync.feature +49 -0
- package/features/sync/homepage-grid.feature +43 -0
- package/features/sync/incremental-sync.feature +28 -0
- package/features/syndication/create-draft.feature +35 -0
- package/package.json +58 -0
- package/src/__generated__/schema.graphql +4289 -0
- package/src/__generated__/types.ts +5355 -0
- package/src/__tests__/api.test.ts +678 -0
- package/src/__tests__/auth-route.test.ts +38 -0
- package/src/__tests__/auth-routing.test.ts +462 -0
- package/src/__tests__/auto-detect.test.ts +412 -0
- package/src/__tests__/binding-guard.test.ts +256 -0
- package/src/__tests__/config.test.ts +212 -0
- package/src/__tests__/converter.test.ts +289 -0
- package/src/__tests__/credential.test.ts +332 -0
- package/src/__tests__/domain.test.ts +341 -0
- package/src/__tests__/downloader.test.ts +679 -0
- package/src/__tests__/folder-detection.test.ts +289 -0
- package/src/__tests__/force-fresh-login.test.ts +236 -0
- package/src/__tests__/main.test.ts +2437 -0
- package/src/__tests__/progress.test.ts +93 -0
- package/src/__tests__/session.test.ts +375 -0
- package/src/__tests__/social-integration.test.ts +386 -0
- package/src/__tests__/social-sync-logic.test.ts +107 -0
- package/src/__tests__/social.test.ts +788 -0
- package/src/__tests__/sync.test.ts +1273 -0
- package/src/__tests__/syndication-toast-law.test.ts +649 -0
- package/src/__tests__/syndication.test.ts +125 -0
- package/src/__tests__/test-profile-escape.test.ts +209 -0
- package/src/__tests__/url-detect.test.ts +79 -0
- package/src/__tests__/utils.test.ts +226 -0
- package/src/api.ts +1366 -0
- package/src/auth-route.ts +38 -0
- package/src/config.ts +80 -0
- package/src/converter.ts +305 -0
- package/src/credential.ts +329 -0
- package/src/domain.ts +183 -0
- package/src/downloader.ts +761 -0
- package/src/main.ts +2092 -0
- package/src/progress.ts +89 -0
- package/src/queries/user.graphql +85 -0
- package/src/queries/viewer.graphql +104 -0
- package/src/social.ts +413 -0
- package/src/sync.ts +818 -0
- package/src/types.ts +477 -0
- package/src/url-detect.ts +49 -0
- package/src/utils.ts +305 -0
- package/test-fixtures/syndication-test-site/input/index.md +8 -0
- package/test-fixtures/syndication-test-site/input/posts/rich-test-article.md +90 -0
- package/test-helpers/TEST_ACCOUNT.md +151 -0
- package/test-helpers/api-client.ts +252 -0
- package/test-helpers/fixtures/articles.ts +147 -0
- package/test-helpers/wallet-auth.ts +305 -0
- package/test-setup/e2e.ts +93 -0
- package/tsconfig.json +23 -0
- package/vitest.config.ts +39 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Feature: Article Sync from Matters
|
|
2
|
+
As a content creator
|
|
3
|
+
I want to sync my Matters articles locally
|
|
4
|
+
So that I can edit them offline
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given a mock Tauri environment
|
|
8
|
+
And an in-memory filesystem
|
|
9
|
+
|
|
10
|
+
Scenario: Sync creates markdown files with frontmatter
|
|
11
|
+
Given sample articles with titles and content
|
|
12
|
+
When I sync articles to local files
|
|
13
|
+
Then markdown files should be created in "article/" folder
|
|
14
|
+
And each file should have frontmatter with title and date
|
|
15
|
+
And each file should have the article content as markdown
|
|
16
|
+
|
|
17
|
+
Scenario: Sync respects Chinese language preference
|
|
18
|
+
Given a user with language preference "zh_hant"
|
|
19
|
+
And sample articles with titles and content
|
|
20
|
+
When I sync articles to local files
|
|
21
|
+
Then articles should be in the localized folder
|
|
22
|
+
And drafts folder should use localized name
|
|
23
|
+
|
|
24
|
+
Scenario: Sync skips unchanged articles
|
|
25
|
+
Given an existing article file with matching date
|
|
26
|
+
And a remote article with the same date
|
|
27
|
+
When I sync articles to local files
|
|
28
|
+
Then the article should be skipped
|
|
29
|
+
And the result should report 1 skipped
|
|
30
|
+
|
|
31
|
+
Scenario: Sync updates newer remote articles
|
|
32
|
+
Given an existing article file from yesterday
|
|
33
|
+
And a remote article revised today
|
|
34
|
+
When I sync articles to local files
|
|
35
|
+
Then the article should be updated
|
|
36
|
+
And the result should report 1 updated
|
|
37
|
+
|
|
38
|
+
Scenario: Sync creates homepage with user profile
|
|
39
|
+
Given a user profile with displayName "Test User"
|
|
40
|
+
When I sync to local files
|
|
41
|
+
Then index.md should be created at project root
|
|
42
|
+
And the homepage should have the displayName as title
|
|
43
|
+
|
|
44
|
+
Scenario: Sync handles collections in folder mode
|
|
45
|
+
Given articles that each belong to one collection
|
|
46
|
+
When I sync to local files
|
|
47
|
+
Then collection folders should be created
|
|
48
|
+
And articles should be placed inside their collection folder
|
|
49
|
+
And collection index.md should be created with title and description
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Feature: Homepage Grid from Pinned Works
|
|
2
|
+
As a content creator using Matters.town
|
|
3
|
+
I want my homepage to show pinned works as a grid
|
|
4
|
+
So that visitors see my featured content prominently
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given a mock Tauri environment
|
|
8
|
+
And an in-memory filesystem
|
|
9
|
+
|
|
10
|
+
Scenario: Homepage grid from pinned collections
|
|
11
|
+
Given a user profile with pinned collections "Travel Notes" and "Tech Essays"
|
|
12
|
+
And no existing homepage
|
|
13
|
+
When I sync to local files
|
|
14
|
+
Then index.md should contain ":::grid 3"
|
|
15
|
+
And index.md should link to each pinned collection
|
|
16
|
+
|
|
17
|
+
Scenario: Homepage grid with mixed pinned works
|
|
18
|
+
Given a user profile with a pinned collection "My Series" and a pinned article "Featured Post"
|
|
19
|
+
And no existing homepage
|
|
20
|
+
When I sync to local files
|
|
21
|
+
Then index.md should contain ":::grid 3"
|
|
22
|
+
And index.md should link to both the collection and article
|
|
23
|
+
|
|
24
|
+
Scenario: No grid when no pinned works
|
|
25
|
+
Given a user profile with no pinned works
|
|
26
|
+
And no existing homepage
|
|
27
|
+
When I sync to local files
|
|
28
|
+
Then index.md should NOT contain ":::grid"
|
|
29
|
+
And index.md should contain the user bio
|
|
30
|
+
|
|
31
|
+
Scenario: Skip homepage when already exists
|
|
32
|
+
Given a user profile with pinned collections
|
|
33
|
+
And an existing homepage with custom content
|
|
34
|
+
When I sync to local files
|
|
35
|
+
Then the existing homepage should be preserved
|
|
36
|
+
And index.md should NOT contain ":::grid"
|
|
37
|
+
|
|
38
|
+
Scenario: Collection order in folder mode
|
|
39
|
+
Given a collection "My Series" with ordered articles "first", "second", "third"
|
|
40
|
+
When I sync to local files
|
|
41
|
+
Then the collection index.md should have an order field
|
|
42
|
+
And the order should list articles as bare slugs
|
|
43
|
+
And the order should match the Matters API ordering
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@e2e @real-api
|
|
2
|
+
Feature: Incremental Article Sync
|
|
3
|
+
As a user, I want to sync only articles modified since my last sync
|
|
4
|
+
So that I save bandwidth and time
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given I am using the Matters test environment
|
|
8
|
+
And I have a test user with articles
|
|
9
|
+
|
|
10
|
+
Scenario: First sync fetches all articles and saves timestamp
|
|
11
|
+
Given I have no previous sync timestamp
|
|
12
|
+
When I run the sync process
|
|
13
|
+
Then all articles should be fetched
|
|
14
|
+
And the config should contain a lastSyncedAt timestamp
|
|
15
|
+
|
|
16
|
+
Scenario: Subsequent sync only fetches newer articles
|
|
17
|
+
Given I have a lastSyncedAt timestamp from 1 hour ago
|
|
18
|
+
And the test user has multiple articles
|
|
19
|
+
When I run the sync process
|
|
20
|
+
Then only recently modified articles should be fetched
|
|
21
|
+
And the lastSyncedAt timestamp should be updated
|
|
22
|
+
|
|
23
|
+
Scenario: Sync skips unchanged articles when no modifications
|
|
24
|
+
Given I have synced all articles recently
|
|
25
|
+
And no articles have been modified since
|
|
26
|
+
When I run the sync process again
|
|
27
|
+
Then 0 articles should be fetched
|
|
28
|
+
And existing local files should remain unchanged
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@e2e @real-api
|
|
2
|
+
Feature: Create Draft on Matters
|
|
3
|
+
As a user, I want to syndicate my local articles to Matters
|
|
4
|
+
So that I can publish to both platforms
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given I am authenticated with the Matters test environment
|
|
8
|
+
|
|
9
|
+
Scenario: Create draft via API
|
|
10
|
+
Given I have an article with title "E2E Test Article"
|
|
11
|
+
And the article has content and tags
|
|
12
|
+
When I create a draft on Matters
|
|
13
|
+
Then a draft should be created with the correct title
|
|
14
|
+
And the draft should have publishState "unpublished"
|
|
15
|
+
And I should receive a draft ID
|
|
16
|
+
|
|
17
|
+
Scenario: Draft includes canonical link
|
|
18
|
+
Given I have an article with canonical URL "https://my-site.com/test-article"
|
|
19
|
+
And add_canonical_link is enabled
|
|
20
|
+
When I create a draft on Matters
|
|
21
|
+
Then the draft content should contain the canonical URL
|
|
22
|
+
And it should be formatted as a link at the end
|
|
23
|
+
|
|
24
|
+
Scenario: Fetch draft by ID
|
|
25
|
+
Given I have created a draft on Matters
|
|
26
|
+
When I fetch the draft by ID
|
|
27
|
+
Then I should receive the draft details
|
|
28
|
+
And the draft should have the correct title
|
|
29
|
+
And the publishState should be present
|
|
30
|
+
|
|
31
|
+
Scenario: Skip already syndicated articles
|
|
32
|
+
Given I have an article with syndicated URL for Matters
|
|
33
|
+
When I check if the article should be syndicated
|
|
34
|
+
Then the article should be skipped
|
|
35
|
+
And no new draft should be created
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@symbiosis-lab/moss-plugin-matters",
|
|
3
|
+
"version": "1.4.2",
|
|
4
|
+
"description": "Syndicate articles between local system and Matters.town",
|
|
5
|
+
"main": "dist/main.bundle.js",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"moss",
|
|
8
|
+
"plugin",
|
|
9
|
+
"matters.town",
|
|
10
|
+
"syndication"
|
|
11
|
+
],
|
|
12
|
+
"author": "Symbiosis Lab",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public",
|
|
16
|
+
"registry": "https://registry.npmjs.org/",
|
|
17
|
+
"provenance": false
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/Symbiosis-Lab/moss-plugins.git",
|
|
22
|
+
"directory": "matters"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@amiceli/vitest-cucumber": "^5.2.1",
|
|
26
|
+
"@graphql-codegen/cli": "^6.1.0",
|
|
27
|
+
"@graphql-codegen/schema-ast": "^5.0.0",
|
|
28
|
+
"@graphql-codegen/typescript": "^5.0.7",
|
|
29
|
+
"@graphql-codegen/typescript-operations": "^5.0.7",
|
|
30
|
+
"@tauri-apps/api": "^2.9.1",
|
|
31
|
+
"@types/node": "^20.0.0",
|
|
32
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
33
|
+
"chokidar-cli": "^3.0.0",
|
|
34
|
+
"concurrently": "^8.2.0",
|
|
35
|
+
"esbuild": "^0.27.0",
|
|
36
|
+
"ethers": "^6.13.0",
|
|
37
|
+
"happy-dom": "^20.0.11",
|
|
38
|
+
"typescript": "^5.3.0",
|
|
39
|
+
"vitest": "^3.2.4",
|
|
40
|
+
"@symbiosis-lab/moss-api": "0.10.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "npm run clean && npm run bundle && npm run copy-assets",
|
|
44
|
+
"dev": "npm run clean && npm run copy-assets && concurrently \"esbuild src/main.ts --bundle --format=iife --global-name=MattersPlugin --outfile=dist/main.bundle.js --watch\" \"npm run watch-assets\"",
|
|
45
|
+
"bundle": "esbuild src/main.ts --bundle --format=iife --global-name=MattersPlugin --outfile=dist/main.bundle.js",
|
|
46
|
+
"clean": "rm -rf dist && mkdir -p dist",
|
|
47
|
+
"copy-assets": "cp assets/* dist/",
|
|
48
|
+
"watch-assets": "chokidar 'assets/**/*' -c 'npm run copy-assets'",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest",
|
|
51
|
+
"test:coverage": "vitest run --project unit --coverage",
|
|
52
|
+
"test:unit": "vitest run --project unit",
|
|
53
|
+
"test:features": "vitest run --project features",
|
|
54
|
+
"test:e2e": "vitest run --project e2e",
|
|
55
|
+
"codegen": "graphql-codegen --config codegen.ts",
|
|
56
|
+
"codegen:watch": "graphql-codegen --config codegen.ts --watch"
|
|
57
|
+
}
|
|
58
|
+
}
|