Skip to content

Commit 20f34ca

Browse files
authored
Merge pull request #83 from omnivore-app/add-note
add note variable to the article and highlight template
2 parents 8610e18 + 866528f commit 20f34ca

File tree

2 files changed

+98
-64
lines changed

2 files changed

+98
-64
lines changed

src/index.ts

Lines changed: 80 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
escapeQuotationMarks,
1515
formatDate,
1616
getHighlightLocation,
17+
HighlightType,
1718
loadArticles,
1819
loadDeletedArticleSlugs,
1920
PageType,
@@ -45,6 +46,7 @@ interface Settings {
4546
highlightTemplate: string
4647
loading: boolean
4748
syncJobId: number
49+
endpoint: string
4850
}
4951

5052
const siteNameFromUrl = (originalArticleUrl: string): string => {
@@ -95,6 +97,7 @@ const fetchOmnivore = async (inBackground = false) => {
9597
highlightTemplate,
9698
graph,
9799
loading,
100+
endpoint,
98101
} = logseq.settings as Settings
99102
// prevent multiple fetches
100103
if (loading) {
@@ -180,7 +183,8 @@ const fetchOmnivore = async (inBackground = false) => {
180183
parseDateTime(syncAt).toISO(),
181184
getQueryFromFilter(filter, customQuery),
182185
true,
183-
'markdown'
186+
'markdown',
187+
endpoint
184188
)
185189

186190
const articleBatch: IBatchBlock[] = []
@@ -194,8 +198,11 @@ const fetchOmnivore = async (inBackground = false) => {
194198
const datePublished = article.publishedAt
195199
? formatDate(new Date(article.publishedAt), preferredDateFormat)
196200
: undefined
201+
const note = article.highlights?.find(
202+
(h) => h.type === HighlightType.Note
203+
)
197204
// Build content string based on template
198-
const articleView = {
205+
const articleVariables = {
199206
title: article.title,
200207
omnivoreUrl: `https://omnivore.app/me/${article.slug}`,
201208
siteName,
@@ -205,12 +212,15 @@ const fetchOmnivore = async (inBackground = false) => {
205212
dateSaved,
206213
content: article.content,
207214
datePublished,
215+
note: note?.annotation,
208216
}
209-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
210-
const content = render(articleTemplate, articleView)
217+
// filter out notes and redactions
218+
const highlights = article.highlights?.filter(
219+
(h) => h.type === HighlightType.Highlight
220+
)
211221
// sort highlights by location if selected in options
212-
highlightOrder === HighlightOrder.LOCATION &&
213-
article.highlights?.sort((a, b) => {
222+
if (highlightOrder === HighlightOrder.LOCATION) {
223+
highlights?.sort((a, b) => {
214224
try {
215225
if (article.pageType === PageType.File) {
216226
// sort by location in file
@@ -225,12 +235,13 @@ const fetchOmnivore = async (inBackground = false) => {
225235
return compareHighlightsInFile(a, b)
226236
}
227237
})
228-
const highlightBatch: (IBatchBlock & { id: string })[] =
229-
article.highlights?.map((it) => {
238+
}
239+
const highlightBatch: IBatchBlock[] =
240+
highlights?.map((it) => {
230241
// Build content string based on template
231242
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
232243
const content = render(highlightTemplate, {
233-
...articleView,
244+
...articleVariables,
234245
text: it.quote,
235246
labels: it.labels,
236247
highlightUrl: `https://omnivore.app/me/${article.slug}#${it.id}`,
@@ -245,7 +256,9 @@ const fetchOmnivore = async (inBackground = false) => {
245256
return {
246257
content,
247258
children: noteChild ? [noteChild] : undefined,
248-
id: it.id,
259+
properties: {
260+
id: it.id,
261+
},
249262
}
250263
}) || []
251264

@@ -265,45 +278,48 @@ const fetchOmnivore = async (inBackground = false) => {
265278
[(clojure.string/includes? ?c "${article.slug}")]]`
266279
)
267280
).flat()
281+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
282+
const articleContent = render(articleTemplate, articleVariables)
268283
if (existingBlocks.length > 0) {
269284
isNewArticle = false
270285
const existingBlock = existingBlocks[0]
271286
// update the first existing block
272-
if (existingBlock.content !== content) {
273-
await logseq.Editor.updateBlock(existingBlock.uuid, content)
287+
if (existingBlock.content !== articleContent) {
288+
await logseq.Editor.updateBlock(existingBlock.uuid, articleContent)
274289
}
275290
// delete the rest of the existing blocks
276291
await deleteBlocks(existingBlocks.slice(1))
277-
if (highlightBatch.length > 0) {
278-
// append highlights to existing block
279-
for (const highlight of highlightBatch) {
280-
const existingHighlights = (
281-
await logseq.DB.datascriptQuery<BlockEntity[]>(
282-
`[:find (pull ?b [*])
292+
// append highlights to existing block
293+
for (const highlight of highlightBatch) {
294+
const existingHighlights = (
295+
await logseq.DB.datascriptQuery<BlockEntity[]>(
296+
`[:find (pull ?b [*])
283297
:where
284298
[?b :block/parent ?p]
285299
[?p :block/uuid ?u]
286300
[(str ?u) ?s]
287301
[(= ?s "${existingBlock.uuid}")]
288302
[?b :block/content ?c]
289-
[(clojure.string/includes? ?c "${highlight.id}")]]`
290-
)
291-
).flat()
292-
if (existingHighlights.length > 0) {
293-
const existingHighlight = existingHighlights[0]
294-
// update existing highlight if content is different
295-
existingHighlight.content !== highlight.content &&
296-
(await logseq.Editor.updateBlock(
297-
existingHighlight.uuid,
298-
highlight.content
299-
))
300-
301-
// checking notes
302-
const noteChild = highlight.children?.[0]
303-
if (noteChild) {
304-
const existingNotes = (
305-
await logseq.DB.datascriptQuery<BlockEntity[]>(
306-
`[:find (pull ?b [*])
303+
[(clojure.string/includes? ?c "${
304+
highlight.properties?.id as string
305+
}")]]`
306+
)
307+
).flat()
308+
if (existingHighlights.length > 0) {
309+
const existingHighlight = existingHighlights[0]
310+
// update existing highlight if content is different
311+
existingHighlight.content !== highlight.content &&
312+
(await logseq.Editor.updateBlock(
313+
existingHighlight.uuid,
314+
highlight.content
315+
))
316+
317+
// checking notes
318+
const noteChild = highlight.children?.[0]
319+
if (noteChild) {
320+
const existingNotes = (
321+
await logseq.DB.datascriptQuery<BlockEntity[]>(
322+
`[:find (pull ?b [*])
307323
:where
308324
[?b :block/parent ?p]
309325
[?p :block/uuid ?u]
@@ -313,32 +329,31 @@ const fetchOmnivore = async (inBackground = false) => {
313329
[(= ?c "${escapeQuotationMarks(
314330
noteChild.content
315331
)}")]]`
316-
)
317-
).flat()
318-
if (existingNotes.length == 0) {
319-
// append new note
320-
await logseq.Editor.insertBlock(
321-
existingHighlight.uuid,
322-
noteChild.content,
323-
{ sibling: false }
324-
)
325-
}
332+
)
333+
).flat()
334+
if (existingNotes.length == 0) {
335+
// append new note
336+
await logseq.Editor.insertBlock(
337+
existingHighlight.uuid,
338+
noteChild.content,
339+
{ sibling: false }
340+
)
326341
}
327-
} else {
328-
// append new highlight
329-
await logseq.Editor.insertBatchBlock(
330-
existingBlock.uuid,
331-
highlight,
332-
{ sibling: false }
333-
)
334342
}
343+
} else {
344+
// append new highlight
345+
await logseq.Editor.insertBatchBlock(
346+
existingBlock.uuid,
347+
highlight,
348+
{ sibling: false }
349+
)
335350
}
336351
}
337352
}
338353

339354
isNewArticle &&
340355
articleBatch.unshift({
341-
content,
356+
content: articleContent,
342357
children: highlightBatch,
343358
})
344359
}
@@ -360,7 +375,8 @@ const fetchOmnivore = async (inBackground = false) => {
360375
apiKey,
361376
after,
362377
size,
363-
parseDateTime(syncAt).toISO()
378+
parseDateTime(syncAt).toISO(),
379+
endpoint
364380
)
365381

366382
for (const slug of deletedArticleSlugs) {
@@ -517,7 +533,7 @@ const main = async (baseInfo: LSPluginBaseInfo) => {
517533
type: 'string',
518534
title: 'Enter the template to use for new articles',
519535
description:
520-
'Enter the template to use for new articles. Required variables are: {{{title}}}, {{{omnivoreUrl}}}. Optional variables are: {{{siteName}}}, {{{originalUrl}}}, {{{author}}}, {{{labels}}}, {{{dateSaved}}}, {{{datePublished}}}',
536+
'We use {{ mustache }} template: http://mustache.github.io/mustache.5.html. Required variables are: title, omnivoreUrl. Optional variables are: siteName, originalUrl, author, labels, dateSaved, datePublished, note',
521537
default: `[{{{title}}}]({{{omnivoreUrl}}})
522538
collapsed:: true
523539
site:: {{#siteName}}[{{{siteName}}}]{{/siteName}}({{{originalUrl}}})
@@ -538,10 +554,17 @@ date-published:: {{{datePublished}}}
538554
type: 'string',
539555
title: 'Enter the template to use for new highlights',
540556
description:
541-
'Enter the template to use for new highlights. Required variables are: {{{text}}}, {{{highlightUrl}}}. Optional variables are {{{dateHighlighted}}}. You can also use the variables in the article template.',
557+
'We use {{ mustache }} template: http://mustache.github.io/mustache.5.html. Required variables are: text, highlightUrl. Optional variables are dateHighlighted. You can also use the variables in the article template.',
542558
default: `> {{{text}}} [⤴️]({{{highlightUrl}}}) {{#labels}} #[[{{{name}}}]] {{/labels}}`,
543559
inputAs: 'textarea',
544560
},
561+
{
562+
key: 'endpoint',
563+
type: 'string',
564+
title: 'API Endpoint',
565+
description: "Enter the Omnivore server's API endpoint",
566+
default: 'https://api-prod.omnivore.app/api/graphql',
567+
},
545568
]
546569
logseq.useSettingsSchema(settingsSchema)
547570

src/util.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { format } from 'date-fns'
12
import { diff_match_patch } from 'diff-match-patch'
23
import { DateTime } from 'luxon'
34
import escape from 'markdown-escape'
4-
import { format } from 'date-fns'
55

66
export const DATE_FORMAT_W_OUT_SECONDS = "yyyy-MM-dd'T'HH:mm"
77
export const DATE_FORMAT = `${DATE_FORMAT_W_OUT_SECONDS}:ss`
@@ -72,13 +72,20 @@ export interface Label {
7272
name: string
7373
}
7474

75+
export enum HighlightType {
76+
Highlight = 'HIGHLIGHT',
77+
Note = 'NOTE',
78+
Redaction = 'REDACTION',
79+
}
80+
7581
export interface Highlight {
7682
id: string
7783
quote: string
7884
annotation: string
7985
patch: string
8086
updatedAt: string
8187
labels?: Label[]
88+
type: HighlightType
8289
}
8390

8491
export interface HighlightPoint {
@@ -95,9 +102,10 @@ const requestHeaders = (apiKey: string) => ({
95102

96103
export const loadArticle = async (
97104
slug: string,
98-
apiKey: string
105+
apiKey: string,
106+
endpoint = ENDPOINT
99107
): Promise<Article> => {
100-
const res = await fetch(ENDPOINT, {
108+
const res = await fetch(endpoint, {
101109
headers: requestHeaders(apiKey),
102110
body: `{"query":"\\n query GetArticle(\\n $username: String!\\n $slug: String!\\n ) {\\n article(username: $username, slug: $slug) {\\n ... on ArticleSuccess {\\n article {\\n ...ArticleFields\\n highlights {\\n ...HighlightFields\\n }\\n labels {\\n ...LabelFields\\n }\\n }\\n }\\n ... on ArticleError {\\n errorCodes\\n }\\n }\\n }\\n \\n fragment ArticleFields on Article {\\n savedAt\\n }\\n\\n \\n fragment HighlightFields on Highlight {\\n id\\n quote\\n annotation\\n }\\n\\n \\n fragment LabelFields on Label {\\n name\\n }\\n\\n","variables":{"username":"me","slug":"${slug}"}}`,
103111
method: 'POST',
@@ -114,9 +122,10 @@ export const loadArticles = async (
114122
updatedAt = '',
115123
query = '',
116124
includeContent = false,
117-
format = 'html'
125+
format = 'html',
126+
endpoint = ENDPOINT
118127
): Promise<[Article[], boolean]> => {
119-
const res = await fetch(ENDPOINT, {
128+
const res = await fetch(endpoint, {
120129
headers: requestHeaders(apiKey),
121130
body: JSON.stringify({
122131
query: `
@@ -146,6 +155,7 @@ export const loadArticles = async (
146155
labels {
147156
name
148157
}
158+
type
149159
}
150160
labels {
151161
name
@@ -184,9 +194,10 @@ export const loadDeletedArticleSlugs = async (
184194
apiKey: string,
185195
after = 0,
186196
first = 10,
187-
updatedAt = ''
197+
updatedAt = '',
198+
endpoint = ENDPOINT
188199
): Promise<[string[], boolean]> => {
189-
const res = await fetch(ENDPOINT, {
200+
const res = await fetch(endpoint, {
190201
headers: requestHeaders(apiKey),
191202
body: `{"query":"\\n query UpdatesSince($after: String, $first: Int, $since: Date!) {\\n updatesSince(first: $first, after: $after, since: $since) {\\n ... on UpdatesSinceSuccess {\\n edges {\\n updateReason\\n node {\\n slug\\n }\\n }\\n pageInfo {\\n hasNextPage\\n }\\n }\\n ... on UpdatesSinceError {\\n errorCodes\\n }\\n }\\n }\\n ","variables":{"after":"${after}","first":${first}, "since":"${
192203
updatedAt || '2021-01-01'

0 commit comments

Comments
 (0)