@pkcprotocol/active-page-sort 0.0.2 → 0.0.4
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/AGENTS.md +12 -3
- package/README.md +8 -6
- package/dist/active-page-sort.js +9 -4
- package/dist/active-page-sort.js.map +1 -1
- package/dist/no-bump.d.ts +24 -1
- package/dist/no-bump.js +43 -0
- package/dist/no-bump.js.map +1 -1
- package/dist/types.d.ts +18 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -27,9 +27,18 @@ Conventions specific to this package:
|
|
|
27
27
|
this package. A rename is a new contract, never an edit. The literal is pinned in `test/unit/no-bump.test.ts`.
|
|
28
28
|
- The match is a whole line equal to the keyword, exact and case-sensitive. `src/no-bump.ts` imports
|
|
29
29
|
nothing and must keep matching what the README describes, because UIs copy or bundle it for the browser.
|
|
30
|
-
- `score` is sync
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
- `score` is sync and never returns `null`: a saged thread sinks, it is not filtered. It reads
|
|
31
|
+
`comment.timestamp`, `commentUpdate.cid`, the reserved `exclude*` options, and per reply `parentCid`,
|
|
32
|
+
`timestamp`, `content`, and the CommentUpdate's `cid`, `removed`, `approved`, `pendingApproval` and
|
|
33
|
+
`edit.deleted`. There is no database access and no network; a need for either is a later iteration of
|
|
34
|
+
the pkc-js contract, not a reason to reach around it.
|
|
35
|
+
- `applyReplyExclusions` (in `src/no-bump.ts`) re-applies pkc-js's reply exclusions inside `score`. On the
|
|
36
|
+
community it is a no-op, the list is already filtered; on a client it turns a raw reply-page walk into
|
|
37
|
+
the set the community scored. It must keep matching pkc-js's `applyPageSortExclusions` and its subtree
|
|
38
|
+
cut (`createDescendantsLookup`, `src/pages/page-sort-scoring.ts`), flag parsing included (trimmed,
|
|
39
|
+
case-insensitive `true`). A new reserved exclusion in pkc-js means a release here.
|
|
40
|
+
`excludeCommentsWithDifferentCommunityAddress` is left out on purpose: `score` has no community address
|
|
41
|
+
(pkc-js#401).
|
|
33
42
|
- The scorer ignores `commentUpdate.lastReplyTimestamp` on purpose. That aggregate counts saged replies.
|
|
34
43
|
- `validatePageSortSettings` is sync and rejects only what can never work (empty list, line break, size
|
|
35
44
|
bounds). An unset option is valid and means plain bump order.
|
package/README.md
CHANGED
|
@@ -22,10 +22,11 @@ The word `sage` appears nowhere in this package. The board supplies its vocabula
|
|
|
22
22
|
pkc-js regenerates a community's post pages on every publish cycle. For each configured sort it calls the sort file's `score` once per post, higher scores first, equal scores in insertion order. Because this sort declares `requireReplies`, pkc-js hands `score` every descendant of the post as one flat list (reduced by the sort's exclusion options, so removed or deleted replies are already gone, together with their subtrees), and the score is:
|
|
23
23
|
|
|
24
24
|
```
|
|
25
|
-
|
|
25
|
+
counted = replies reachable from the post through replies the exclusion options keep
|
|
26
|
+
max(post.timestamp, ...counted.filter(not no-bump).map(reply => reply.timestamp))
|
|
26
27
|
```
|
|
27
28
|
|
|
28
|
-
That is the whole algorithm. pkc-js owns everything around it: pinned threads first (`pinnedFirst`), the optional age window (`maxAge`), chunking into pages, the moderation exclusions. The file contains no date arithmetic and never sees a pinned flag.
|
|
29
|
+
On the community the first line changes nothing: pkc-js already applied the exclusions. It is there for clients. The reply pages a UI walks keep deleted and removed replies, so `score` applies the published `exclude*` options itself, which makes a raw walk land on the community's order (see [Re-sort a page locally](#4-re-sort-a-page-locally-optional)). That is the whole algorithm. pkc-js owns everything around it: pinned threads first (`pinnedFirst`), the optional age window (`maxAge`), chunking into pages, the moderation exclusions. The file contains no date arithmetic and never sees a pinned flag.
|
|
29
30
|
|
|
30
31
|
The same `score` function runs on a client that installed this package, so a UI can re-sort a page it holds and land on the community's order. See [For UI developers](#for-ui-developers).
|
|
31
32
|
|
|
@@ -120,9 +121,9 @@ Page sort options are strings, like challenge options. Unlike challenge options
|
|
|
120
121
|
| `noBumpKeywords` | no | yes, unless listed in `privateOptions` | unset (plain bump order) | Comma-separated keywords, e.g. `sage` or `sage,nobump`. A reply whose content has a whole line equal to one of these does not bump its thread. Exact and case-sensitive |
|
|
121
122
|
| `maxAge` | no | always (reserved) | none | pkc-js reserved: a sliding window such as `"36h"`, `"7d"`, `"2w"`, `"1M"`, `"1y"`. Threads older than the window drop out of the pages (pinned threads bypass it) |
|
|
122
123
|
| `pinnedFirst` | no | always (reserved) | `"true"` | pkc-js reserved: pinned threads first and outside the window. `"false"` treats them as ordinary threads |
|
|
123
|
-
| `excludeRemovedComments`, `excludeDeletedComments`, `excludeCommentPendingApproval`, `excludeCommentWithApprovedFalse`, `excludeCommentsWithDifferentCommunityAddress` | no | always (reserved) | `"true"` for the `posts` scope | pkc-js reserved moderation filters on the comment set the sort starts from. A reply excluded here
|
|
124
|
+
| `excludeRemovedComments`, `excludeDeletedComments`, `excludeCommentPendingApproval`, `excludeCommentWithApprovedFalse`, `excludeCommentsWithDifferentCommunityAddress` | no | always (reserved) | `"true"` for the `posts` scope | pkc-js reserved moderation filters on the comment set the sort starts from. A reply excluded here, and everything under it, does not count toward a bump. `score` re-applies the first four to the replies it receives, so a client's raw walk scores like the community; `excludeCommentsWithDifferentCommunityAddress` needs the community's address, which `score` does not get, and is left to pkc-js ([pkc-js#401](https://github.com/pkcprotocol/pkc-js/issues/401)) |
|
|
124
125
|
|
|
125
|
-
Keep `noBumpKeywords` public unless you have a reason not to: a UI reads it to know the board supports sage, to put the keyword on the wire the way the sort reads it, and to mark saged replies. With the option private the order still applies but UIs cannot do any of that. The reserved options cannot be made private (`ERR_PAGE_SORT_RESERVED_OPTION_CANNOT_BE_PRIVATE`): a client re-sorting a page must know how its comment set was filtered. Their full semantics are in the pkc-js page sorts doc, "Reserved options".
|
|
126
|
+
Keep `noBumpKeywords` public unless you have a reason not to: a UI reads it to know the board supports sage, to put the keyword on the wire the way the sort reads it, and to mark saged replies. With the option private the order still applies but UIs cannot do any of that. The reserved options cannot be made private (`ERR_PAGE_SORT_RESERVED_OPTION_CANNOT_BE_PRIVATE`): a client re-sorting a page must know how its comment set was filtered. Their full semantics are in the pkc-js page sorts doc, "Reserved options". `score` mirrors pkc-js's handling of the exclusion flags it can apply; if pkc-js adds a reserved exclusion, this package needs a release that applies it too, until then a client re-sort counts replies the new flag drops.
|
|
126
127
|
|
|
127
128
|
### Validation
|
|
128
129
|
|
|
@@ -189,11 +190,11 @@ import { isNoBumpReplyForOptions } from "@pkcprotocol/active-page-sort";
|
|
|
189
190
|
const saged = isNoBumpReplyForOptions(reply.content, community.pageSorts?.posts?.active?.publicOptions);
|
|
190
191
|
```
|
|
191
192
|
|
|
192
|
-
`isNoBumpContent(content, keywords)` and `splitKeywords(raw)` are the same test without the options lookup, and `bumpTimestamp({ postTimestamp, replies, keywords })` gives a thread's effective bump time. `src/no-bump.ts` imports nothing and bundles for a browser.
|
|
193
|
+
`isNoBumpContent(content, keywords)` and `splitKeywords(raw)` are the same test without the options lookup, and `bumpTimestamp({ postTimestamp, replies, keywords })` gives a thread's effective bump time. For a reply tree walked from reply pages, pass it through `applyReplyExclusions({ postCid, replies, options })` first, with the published `publicOptions`, to drop what the community did not count. `src/no-bump.ts` imports nothing and bundles for a browser.
|
|
193
194
|
|
|
194
195
|
### 4. Re-sort a page locally (optional)
|
|
195
196
|
|
|
196
|
-
pkc-js exports no sorter: the package's `score` is the whole contract. A UI that wants to re-order threads between community publishes (a user's own reply just landed, say) applies `score` itself. This sort declares `requireReplies`, so it needs each thread's replies: walk a flat reply sort (`newFlat` / `oldFlat`) when the post carries one, otherwise the nested sort's pages recursively, at every depth.
|
|
197
|
+
pkc-js exports no sorter: the package's `score` is the whole contract. A UI that wants to re-order threads between community publishes (a user's own reply just landed, say) applies `score` itself. This sort declares `requireReplies`, so it needs each thread's replies: walk a flat reply sort (`newFlat` / `oldFlat`) when the post carries one, otherwise the nested sort's pages recursively, at every depth. Walk all of it: every page of every chain, for every thread you re-sort. `score` receives a plain list and cannot tell a partial walk from a complete one, so a thread whose newest bump is on a page you did not fetch ranks too low, with no error. Hand each post its descendants by `parentCid`, as walked, and pass the published `publicOptions` as `options`. Reply pages keep deleted and removed replies, which the community did not count; `score` drops them, and everything under them, using the published `exclude*` options, so no filtering is needed on the UI side. Pass the options as published: without the `exclude*` flags nothing is dropped. The worked example of the walk and the re-sort is `test/node-and-browser/pages/page-sorts-client-test-util.ts` in pkc-js; this package's own copy of the re-sort is `test/unit/resort-like-a-ui.ts`. A re-sorted page is still one slice of one sort: re-sorting it gives that slice in another order, not the whole board.
|
|
197
198
|
|
|
198
199
|
```ts
|
|
199
200
|
import activePageSort from "@pkcprotocol/active-page-sort";
|
|
@@ -217,6 +218,7 @@ Treat `community.pageSorts[].name` as data: look it up in your own registry, nev
|
|
|
217
218
|
| `SORT_NAME`, `DESCRIPTION`, `optionInputs`, `validatePageSortSettings` | The file's declared surface, for config UIs and tests |
|
|
218
219
|
| `NO_BUMP_KEYWORDS_OPTION` | `"noBumpKeywords"`, the option key. Renaming it is a new contract |
|
|
219
220
|
| `splitKeywords`, `isNoBumpContent`, `bumpTimestamp`, `isNoBumpReplyForOptions` | The matching rules, import-free, for browsers |
|
|
221
|
+
| `applyReplyExclusions`, `EXCLUSION_OPTIONS` | The replies a thread's bump counts: the published `exclude*` options applied to a walked reply tree, subtrees of dropped replies cut. Import-free |
|
|
220
222
|
| `PageSortFile`, `PageSortFileInput`, `PageSortFileFactory`, `PageSortFileFactoryInput`, `PageSortFileFactoryArgs`, `PageSortScoreArgs`, `PageSortReplyEntry`, `PageSortScope`, `CommunityPageSortSetting` | Re-exported pkc-js types (root exports since pkc-js 0.0.110) |
|
|
221
223
|
| `PageSortSettingsEntry` | Alias of `CommunityPageSortSetting`, the `settings.pages` entry the factory receives |
|
|
222
224
|
|
package/dist/active-page-sort.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NO_BUMP_KEYWORDS_OPTION, bumpTimestamp, isNoBumpContent, splitKeywords } from "./no-bump.js";
|
|
1
|
+
import { NO_BUMP_KEYWORDS_OPTION, applyReplyExclusions, bumpTimestamp, isNoBumpContent, splitKeywords } from "./no-bump.js";
|
|
2
2
|
/** The wire key: this sort publishes under `community.posts.pages.active` / `pageCids.active`, like the built-in it replaces. */
|
|
3
3
|
export const SORT_NAME = "active";
|
|
4
4
|
export const DESCRIPTION = "Bump order where a reply whose content has a line equal to a configured keyword does not bump its thread";
|
|
@@ -48,9 +48,14 @@ export const activePageSort = ({ pageSortSettings }) => {
|
|
|
48
48
|
requireReplies: true,
|
|
49
49
|
optionInputs,
|
|
50
50
|
defaultOptions: {},
|
|
51
|
-
// MAX(timestamp) over the post and its non-no-bump descendants. pkc-js hands `replies` as one flat
|
|
52
|
-
// every descendant that survived this sort's exclusion options
|
|
53
|
-
|
|
51
|
+
// MAX(timestamp) over the post and its counted, non-no-bump descendants. pkc-js hands `replies` as one flat
|
|
52
|
+
// list of every descendant that survived this sort's exclusion options, so the re-filter is a no-op there; a
|
|
53
|
+
// client passes the reply pages it walked, which keep deleted and removed replies, and the re-filter drops them.
|
|
54
|
+
score: ({ comment, commentUpdate, options, replies }) => bumpTimestamp({
|
|
55
|
+
postTimestamp: comment.timestamp,
|
|
56
|
+
replies: applyReplyExclusions({ postCid: commentUpdate.cid, replies: replies ?? [], options }),
|
|
57
|
+
keywords
|
|
58
|
+
}),
|
|
54
59
|
validatePageSortSettings
|
|
55
60
|
};
|
|
56
61
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-page-sort.js","sourceRoot":"","sources":["../src/active-page-sort.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"active-page-sort.js","sourceRoot":"","sources":["../src/active-page-sort.ts"],"names":[],"mappings":"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"}
|
package/dist/no-bump.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NoBumpReplyLike } from "./types.js";
|
|
1
|
+
import type { ExcludableReplyLike, NoBumpReplyLike } from "./types.js";
|
|
2
2
|
/** The option key under `settings.pages.posts[i].options`. Published as `community.pageSorts.posts.active.publicOptions.noBumpKeywords`. */
|
|
3
3
|
export declare const NO_BUMP_KEYWORDS_OPTION = "noBumpKeywords";
|
|
4
4
|
/** Comma-separated list to keywords: trimmed, empty entries dropped, duplicates kept out. */
|
|
@@ -20,3 +20,26 @@ export declare const bumpTimestamp: ({ postTimestamp, replies, keywords }: {
|
|
|
20
20
|
replies: readonly NoBumpReplyLike[];
|
|
21
21
|
keywords: readonly string[];
|
|
22
22
|
}) => number;
|
|
23
|
+
/**
|
|
24
|
+
* The reserved exclusion options this package re-applies, and what each drops. `excludeCommentsWithDifferentCommunityAddress`
|
|
25
|
+
* is not here: it compares against the community's address, which a sort file is never given (pkc-js#401).
|
|
26
|
+
*/
|
|
27
|
+
export declare const EXCLUSION_OPTIONS: {
|
|
28
|
+
readonly excludeRemovedComments: (update: ExcludableReplyLike["commentUpdate"]) => boolean;
|
|
29
|
+
readonly excludeDeletedComments: (update: ExcludableReplyLike["commentUpdate"]) => boolean;
|
|
30
|
+
readonly excludeCommentWithApprovedFalse: (update: ExcludableReplyLike["commentUpdate"]) => boolean;
|
|
31
|
+
readonly excludeCommentPendingApproval: (update: ExcludableReplyLike["commentUpdate"]) => boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The replies a thread's bump counts: those reachable from the post through replies the `exclude*` options keep.
|
|
35
|
+
* A dropped reply takes everything under it along, and so does a reply whose parent is not in the list. This is
|
|
36
|
+
* pkc-js's own filter and subtree cut for the replies it hands `score`, so on the community it changes nothing.
|
|
37
|
+
* On a client it turns a walk of the reply pages, which keep deleted and removed replies, into the set the
|
|
38
|
+
* community scored. Flags parse like pkc-js parses them: trimmed, case-insensitive `"true"` is on, anything else
|
|
39
|
+
* off. Pass the published `publicOptions`; without the flags nothing is dropped. Linear in the thread's replies.
|
|
40
|
+
*/
|
|
41
|
+
export declare const applyReplyExclusions: <T extends ExcludableReplyLike>({ postCid, replies, options }: {
|
|
42
|
+
postCid: string;
|
|
43
|
+
replies: readonly T[];
|
|
44
|
+
options: Readonly<Record<string, string>>;
|
|
45
|
+
}) => T[];
|
package/dist/no-bump.js
CHANGED
|
@@ -40,4 +40,47 @@ export const bumpTimestamp = ({ postTimestamp, replies, keywords }) => {
|
|
|
40
40
|
}
|
|
41
41
|
return bump;
|
|
42
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* The reserved exclusion options this package re-applies, and what each drops. `excludeCommentsWithDifferentCommunityAddress`
|
|
45
|
+
* is not here: it compares against the community's address, which a sort file is never given (pkc-js#401).
|
|
46
|
+
*/
|
|
47
|
+
export const EXCLUSION_OPTIONS = {
|
|
48
|
+
excludeRemovedComments: (update) => update.removed === true,
|
|
49
|
+
excludeDeletedComments: (update) => update.edit?.deleted === true,
|
|
50
|
+
excludeCommentWithApprovedFalse: (update) => update.approved === false,
|
|
51
|
+
excludeCommentPendingApproval: (update) => update.pendingApproval === true
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The replies a thread's bump counts: those reachable from the post through replies the `exclude*` options keep.
|
|
55
|
+
* A dropped reply takes everything under it along, and so does a reply whose parent is not in the list. This is
|
|
56
|
+
* pkc-js's own filter and subtree cut for the replies it hands `score`, so on the community it changes nothing.
|
|
57
|
+
* On a client it turns a walk of the reply pages, which keep deleted and removed replies, into the set the
|
|
58
|
+
* community scored. Flags parse like pkc-js parses them: trimmed, case-insensitive `"true"` is on, anything else
|
|
59
|
+
* off. Pass the published `publicOptions`; without the flags nothing is dropped. Linear in the thread's replies.
|
|
60
|
+
*/
|
|
61
|
+
export const applyReplyExclusions = ({ postCid, replies, options }) => {
|
|
62
|
+
const active = Object.entries(EXCLUSION_OPTIONS)
|
|
63
|
+
.filter(([option]) => options[option]?.trim().toLowerCase() === "true")
|
|
64
|
+
.map(([, drops]) => drops);
|
|
65
|
+
const childrenOf = new Map();
|
|
66
|
+
for (const reply of replies) {
|
|
67
|
+
const parentCid = reply.comment.parentCid;
|
|
68
|
+
if (!parentCid || active.some((drops) => drops(reply.commentUpdate)))
|
|
69
|
+
continue;
|
|
70
|
+
const siblings = childrenOf.get(parentCid);
|
|
71
|
+
if (siblings)
|
|
72
|
+
siblings.push(reply);
|
|
73
|
+
else
|
|
74
|
+
childrenOf.set(parentCid, [reply]);
|
|
75
|
+
}
|
|
76
|
+
const counted = [];
|
|
77
|
+
const stack = [postCid];
|
|
78
|
+
for (let cid = stack.pop(); cid !== undefined; cid = stack.pop()) {
|
|
79
|
+
for (const child of childrenOf.get(cid) ?? []) {
|
|
80
|
+
counted.push(child);
|
|
81
|
+
stack.push(child.commentUpdate.cid);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return counted;
|
|
85
|
+
};
|
|
43
86
|
//# sourceMappingURL=no-bump.js.map
|
package/dist/no-bump.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-bump.js","sourceRoot":"","sources":["../src/no-bump.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,qGAAqG;AACrG,oFAAoF;AAEpF,4IAA4I;AAC5I,MAAM,CAAC,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAExD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAuB,EAAY,EAAE;IACjE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAgB,EAAE,QAA2B,EAAW,EAAE;IACxF,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClG,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,aAAa,EACb,OAAO,EACP,QAAQ,EAKT,EAAU,EAAE;IACX,IAAI,IAAI,GAAG,aAAa,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;YAAE,SAAS;QAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI;YAAE,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"no-bump.js","sourceRoot":"","sources":["../src/no-bump.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,3 +9,21 @@ export interface NoBumpReplyLike {
|
|
|
9
9
|
content?: string | undefined;
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The subset of a reply `applyReplyExclusions` reads. A `PageSortReplyEntry` and a page entry's `raw` are both
|
|
14
|
+
* supersets; the optional fields accept an explicit `undefined`, as page entries carry them.
|
|
15
|
+
*/
|
|
16
|
+
export interface ExcludableReplyLike {
|
|
17
|
+
comment: {
|
|
18
|
+
parentCid?: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
commentUpdate: {
|
|
21
|
+
cid: string;
|
|
22
|
+
removed?: boolean | undefined;
|
|
23
|
+
approved?: boolean | undefined;
|
|
24
|
+
pendingApproval?: boolean | undefined;
|
|
25
|
+
edit?: {
|
|
26
|
+
deleted?: boolean | undefined;
|
|
27
|
+
} | undefined;
|
|
28
|
+
};
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkcprotocol/active-page-sort",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Bump-order (active) page sort for pkc-js communities where replies carrying a configured keyword, such as sage, do not bump the thread",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|