Skip to content

Commit 4ae048e

Browse files
dwertheimerclaude
andcommitted
Merge branch 'main' into strict-flow-check
Brings in #774 (the np.Preview Flow fix), so the repo is at zero Flow errors with the strict check in place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 parents bcacf3b + 094449b commit 4ae048e

201 files changed

Lines changed: 6426 additions & 1537 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
description: Show actual markdown source (not rendered) for written CLI output
3+
alwaysApply: true
4+
---
5+
6+
# Raw Markdown for Written Output
7+
8+
When the user wants **written output** in the CLI (CHANGELOG summaries, release notes, docs drafts, copy-pasteable text, etc.) -- anything meant to be read or copied as markdown source -- show the **actual markdown characters**, not a rendered version.
9+
10+
## Why
11+
12+
Rendered replies hide `#` / `###` and turn `-` lists into bullet symbols (`•`). The user cannot verify or copy the source as intended.
13+
14+
## Do
15+
16+
- Put that content in a fenced code block (e.g. ` ```markdown ` ... ` ``` `) so `#`, `-`, and other markup stay as plain text.
17+
- Apply this to final deliverable prose, not to agent build plans, tool traces, or normal conversational replies.
18+
19+
## Don't
20+
21+
- Rely on the chat UI's markdown rendering for copy-pasteable written deliverables.
22+
- Use Unicode bullet characters (`•`, `●`, etc.) in place of markdown list markers.
23+
24+
```markdown
25+
<!-- ❌ BAD: rendered in the reply as bullets / headings -->
26+
### New
27+
- Item one
28+
29+
<!-- ✅ GOOD: fenced so source is visible -->
30+
### New
31+
- Item one
32+
```
33+
34+
(The good example must live inside a fenced code block in the real reply.)

‎.hyperlayout.bak-20260730-222314‎

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
{
2+
"COMMENT": "https://github.com/timolins/hyperlayout",
3+
"e-desc": "Everything",
4+
"e": [
5+
[
6+
[
7+
"npm run autowatch",
8+
"./node_modules/.bin/jest ./**/*.test.js --silent --watchAll"
9+
],
10+
""
11+
]
12+
],
13+
"t-desc": "Templating",
14+
"t": [
15+
[
16+
[
17+
"npm run autowatch np.Templating np.MeetingNotes -- --minify",
18+
"jest np.Templating/__tests__/**/*.test.js"
19+
],
20+
""
21+
]
22+
],
23+
"c-desc": "EventAutomations with coverage report",
24+
"c": [
25+
[
26+
"npm run autowatch dwertheimer.EventAutomations",
27+
"jest --watchAll dwertheimer.EventAutomations/**/*.test.js",
28+
"open file:///Users/dwertheimer/Developer/Noteplan/plugins-main-repo/coverage/lcov-report/dwertheimer.EventAutomations/src/NPTimeblocking.js.html && tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep JSLog"
29+
]
30+
],
31+
"v-desc": "FaVorites",
32+
"v": [
33+
[
34+
"node '/Users/dwertheimer/Developer/np-plugins-current/dwertheimer.Favorites/src/support/performRollup.node.js' --watch",
35+
"npm run autowatch dwertheimer.Favorites -COMPACT",
36+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=dwertheimer.Favorites/favorites_browser_output.html"
37+
],
38+
[
39+
"nplog"
40+
]
41+
],
42+
"r-desc": "React dev - TaskAutomations",
43+
"r": [
44+
[
45+
"npm run autowatch dwertheimer.TaskAutomations np.Shared",
46+
"node '/Users/dwertheimer/Developer/np-plugins-current/dwertheimer.TaskAutomations/src/react/support/performRollup.node.js' --watch",
47+
"node '/Users/dwertheimer/Developer/np-plugins-current/np.Shared/src/react/support/performRollup.node.js' --watch",
48+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=dwertheimer.TaskAutomations/reactLocal.html",
49+
"jest **/*.test.js --reporters jest-silent-reporter --reporters ./jest.customSummaryReporter.js"
50+
],
51+
[
52+
"open \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\"; tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep 'JSLog' | grep -v 'WebView Log'",
53+
"tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep 'JSLog' | grep 'WebView Log'"
54+
]
55+
],
56+
"p-desc": "test-plugin-scratch",
57+
"p": [
58+
[
59+
"npm run autowatch dwertheimer.test-plugin-scratch",
60+
"cursor '/Users/dwertheimer/Developer/np-plugins-current/dwertheimer.test-plugin-scratch/src/testPluginScratch.js'"
61+
],
62+
[
63+
"open \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\"; tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep 'JSLog' | grep -v 'WebView Log'",
64+
"tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep 'JSLog' | grep 'WebView Log'"
65+
]
66+
],
67+
"d-desc": "Dashboard",
68+
"d": [
69+
[
70+
"node '/Users/dwertheimer/Developer/np-plugins-current/np.Shared/src/react/support/performRollup.node.js' --watch",
71+
"node '/Users/dwertheimer/Developer/np-plugins-current/jgclark.Dashboard/src/react/support/performRollup.node.js' --watch",
72+
"npm run autowatch jgclark.Dashboard np.Shared -COMPACT"
73+
],
74+
[
75+
"jestall",
76+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=jgclark.Dashboard/dashboard-react.html"
77+
],
78+
[
79+
"nplog"
80+
]
81+
],
82+
"s-desc": "np.Shared",
83+
"s": [
84+
[
85+
"node '/Users/dwertheimer/Developer/np-plugins-current/np.Shared/src/react/support/performRollup.node.js' --watch",
86+
"npm run autowatch np.Shared -COMPACT"
87+
],
88+
[
89+
"jestall",
90+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=np.Shared/form_output.html"
91+
],
92+
[
93+
"nplog"
94+
]
95+
],
96+
"f-desc": "Forms",
97+
"f": [
98+
[
99+
"node '/Users/dwertheimer/Developer/np-plugins-current/np.Shared/src/react/support/performRollup.node.js' --watch",
100+
"node '/Users/dwertheimer/Developer/np-plugins-current/dwertheimer.Forms/src/support/performRollup.node.js' --watch",
101+
"npm run autowatch dwertheimer.Forms np.Shared -COMPACT",
102+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=dwertheimer.Forms"
103+
],
104+
[
105+
"nplog"
106+
]
107+
],
108+
"l-desc": "Dialog Testing",
109+
"l": [
110+
[
111+
"node '/Users/dwertheimer/Developer/np-plugins-current/np.Shared/src/react/support/performRollup.node.js' --watch",
112+
"npm run autowatch np.Shared np.Templating"
113+
],
114+
[
115+
"cd '/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/Plugins';live-server --open=np.Shared/form_output.html"
116+
],
117+
[
118+
"nplog"
119+
]
120+
],
121+
"a-desc": "Event Automations",
122+
"a": [
123+
[
124+
[
125+
"npm run autowatch dwertheimer.EventAutomations",
126+
"./node_modules/.bin/jest ./helpers/**/*.test.js ./dwertheimer.EventAutomations/**/*.test.js --silent --watchAll"
127+
],
128+
[
129+
"tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep JSLog",
130+
""
131+
]
132+
]
133+
],
134+
"x-desc": "Quad split, TBD items",
135+
"x": [
136+
[
137+
[
138+
"echo 'nra'",
139+
"echo 'jest'"
140+
],
141+
[
142+
"open \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\"; tail -f \"/Users/dwertheimer/Library/Containers/co.noteplan.NotePlan3/Data/Library/Application Support/co.noteplan.NotePlan3/np-out.log\" | grep JSLog",
143+
"echo 'shell'"
144+
]
145+
]
146+
]
147+
}

‎aaronpoweruser.ReadwiseUnofficial/src/NPReadwiseHelpers.js‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,25 +46,27 @@ export function removeInvalidChars(string: string): string {
4646
)
4747
}
4848

49+
/**
50+
* Front matter attributes built from a Readwise source, keyed by attribute name.
51+
* Matches the `newAttributes` parameter type of updateFrontMatterVars() in helpers/NPFrontMatter.
52+
*/
53+
export type ReadwiseFrontMatter = { [string]: string }
54+
4955
/**
5056
* Parse readwise data and generate front matter
5157
* @param {*} source - the readwise data as a JSON object
52-
* @returns
58+
* @returns {ReadwiseFrontMatter} - the front matter attributes
5359
*/
54-
export function buildReadwiseFrontMatter(source: any): any {
55-
const frontMatter = {}
56-
// $FlowIgnore[prop-missing] - intentionally setting properties dynamically as frontMatter keys are dynamic
60+
export function buildReadwiseFrontMatter(source: any): ReadwiseFrontMatter {
61+
const frontMatter: ReadwiseFrontMatter = {}
5762
frontMatter.author = `[[${escapeTwitterHandle(source.author)}]]`
5863
if (source.readable_title.toLowerCase().trim() !== source.title.toLowerCase().trim()) {
59-
// $FlowIgnore[prop-missing] - intentionally setting properties dynamically as frontMatter keys are dynamic
6064
frontMatter.long_title = removeInvalidChars(source.title)
6165
}
6266
if (source.book_tags !== null && source.book_tags.length > 0) {
63-
// $FlowIgnore[prop-missing] - intentionally setting properties dynamically as frontMatter keys are dynamic
6467
frontMatter.tags = source.book_tags.map((tag) => `${formatTag(tag.name)}`).join(', ')
6568
}
6669
if (source.unique_url !== null) {
67-
// $FlowIgnore[prop-missing] - we are intentionally setting properties dynamically
6870
frontMatter.url = source.unique_url
6971
}
7072
return frontMatter

‎community-plugins.json‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,12 @@
7575
"author": "Marginal Reader",
7676
"description": "Manage tasks by life role with an interactive panel",
7777
"repo": "marginalreader/role-focus"
78+
},
79+
{
80+
"id": "np.reminders",
81+
"name": "Reminders Import",
82+
"author": "EduardMe",
83+
"description": "Import Apple Reminders into the current note as linked tasks with reminder pills that sync two-way (requires NotePlan 3.21.2+)",
84+
"repo": "EduardMe/noteplan-reminder-import-plugin"
7885
}
79-
]
86+
]

‎dbludeau.TodoistNoteplanSync/src/NPPluginMain.js‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,16 @@ const setup: {
4646
teamAccount: boolean,
4747
addUnassigned: boolean,
4848
header: string,
49-
newFolder: any,
50-
newToken: any,
49+
// the following are write-only aliases: each is backed by a setter that normalises the value into one of the fields above
50+
newFolder: string,
51+
newToken: string,
5152
// useTeamAccount is not in the object literal below; it is created on first write by the teamAccount setter
52-
useTeamAccount?: any,
53-
syncDates: any,
54-
syncPriorities: any,
55-
syncTags: any,
56-
syncUnassigned: any,
57-
newHeader: any,
53+
useTeamAccount?: boolean,
54+
syncDates: boolean,
55+
syncPriorities: boolean,
56+
syncTags: boolean,
57+
syncUnassigned: boolean,
58+
newHeader: string,
5859
} = {
5960
token: '',
6061
folder: 'Todoist',
@@ -79,8 +80,9 @@ const setup: {
7980
// remove leading and tailing slashes
8081
passedFolder = passedFolder.replace(/\/+$/, '')
8182
passedFolder = passedFolder.replace(/^\/+/, '')
82-
// $FlowIgnore[object-this-reference] this setter is only ever reached as `setup.newFolder = x`, so `this` is `setup`
83-
this.folder = passedFolder
83+
// Note: written as `setup.folder` (not `this.folder`) to match the other setters in this object. Flow bans `this` in object-literal
84+
// methods outright, and this setter is only ever reached as `setup.newFolder = x`, so `this` was always `setup` anyway.
85+
setup.folder = passedFolder
8486
},
8587
/**
8688
* @param {boolean} passedSyncDates
@@ -91,7 +93,7 @@ const setup: {
9193
/**
9294
* @param {boolean} passedSyncPriorities
9395
*/
94-
set syncPriorities(passedSyncPriorities: true) {
96+
set syncPriorities(passedSyncPriorities: boolean) {
9597
setup.addPriorities = passedSyncPriorities
9698
},
9799
/**
@@ -104,15 +106,15 @@ const setup: {
104106
* @param {boolean} passedTeamAccount
105107
*/
106108
set teamAccount(passedTeamAccount: boolean) {
107-
// $FlowIgnore[object-this-reference] this setter is only ever reached as `setup.teamAccount = x`, so `this` is `setup`
108-
this.useTeamAccount = passedTeamAccount
109+
// Note: `setup` rather than `this`; see the newFolder setter above.
110+
setup.useTeamAccount = passedTeamAccount
109111
},
110112
/**
111113
* @param {boolean} passedSyncUnassigned
112114
*/
113115
set syncUnassigned(passedSyncUnassigned: boolean) {
114-
// $FlowIgnore[object-this-reference] this setter is only ever reached as `setup.syncUnassigned = x`, so `this` is `setup`
115-
this.addUnassigned = passedSyncUnassigned
116+
// Note: `setup` rather than `this`; see the newFolder setter above.
117+
setup.addUnassigned = passedSyncUnassigned
116118
},
117119
/**
118120
* @param {string} passedHeader

‎dwertheimer.EventAutomations/__tests__/NPTimeblocking.test.js‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,10 @@ describe('dwertheimer.EventAutomations' /* pluginID */, () => {
134134
Editor.note.backlinks = [{ subItems: [{ content: 'line1' }] }]
135135
const spy = jest.spyOn(CommandBar, 'prompt')
136136
await mainFile.insertTodosAsTimeblocks()
137-
// $FlowIgnore - jest doesn't know about this param
138-
expect(spy.mock.lastCall[1]).toEqual(`No todos/references marked for >today`)
137+
// `mock.lastCall` exists at runtime (jest >= 26) but is absent from the `mock` object type in
138+
// flow-typed/npm/jest_v27.x.x.js, so read the last entry of `mock.calls` (which is the same thing) instead
139+
const lastCall = spy.mock.calls[spy.mock.calls.length - 1]
140+
expect(lastCall[1]).toEqual(`No todos/references marked for >today`)
139141
spy.mockRestore()
140142
})
141143
})

‎dwertheimer.EventAutomations/src/NPEventBlocks.js‎

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,21 @@ export type EventBlocksConfig = {
2121
calendar?: string,
2222
}
2323

24-
type ConfirmedEvent = {
24+
/**
25+
* The only paragraph fields the event-block pipeline touches: `content` (read + written back) and
26+
* `type` (read, to skip title lines). Declared structurally and inexactly so that a synthetic
27+
* one-line block (see createEventPrompt) is as acceptable as a real TParagraph read from a note.
28+
*/
29+
export interface EventTextLine {
30+
content: string;
31+
+type: ParagraphType;
32+
}
33+
34+
type ConfirmedEvent<TLine: EventTextLine> = {
2535
revisedLine: string,
2636
originalLine: string,
2737
dateRangeInfo: ParsedTextDateRange,
28-
paragraph: TParagraph,
38+
paragraph: TLine,
2939
index: number,
3040
}
3141

@@ -182,13 +192,13 @@ export async function createEvent(title: string, range: { start: Date, end: Date
182192
* then ask the user to choose the correct one. Return the ConfirmedEvent data for each line to be turned into an event
183193
* Skips blank lines and title lines
184194
* NOTE: Calendar.parseDateText does not correctly return "today at" so we try to fix that here
185-
* @param {Array<TParagraph>} paragraphBlock
195+
* @param {Array<TLine>} paragraphBlock
186196
* @param {EventBlocksConfig} config
187-
* @returns {Promise<Array<ConfirmedEvent>>} - the list of unambiguous event info to create
197+
* @returns {Promise<Array<ConfirmedEvent<TLine>>>} - the list of unambiguous event info to create
188198
*/
189-
export async function confirmEventTiming(paragraphBlock: Array<TParagraph>, config: EventBlocksConfig): Promise<Array<ConfirmedEvent>> {
199+
export async function confirmEventTiming<TLine: EventTextLine>(paragraphBlock: Array<TLine>, config: EventBlocksConfig): Promise<Array<ConfirmedEvent<TLine>>> {
190200
const { confirm /*, removeDateText */ } = config
191-
const confirmedEventData = []
201+
const confirmedEventData: Array<ConfirmedEvent<TLine>> = []
192202
for (let i = 0; i < paragraphBlock.length; i++) {
193203
const line = paragraphBlock[i]
194204
if (hasCalendarLink(line.content) || line.type === 'title' || line.content === '') {
@@ -232,14 +242,14 @@ export async function confirmEventTiming(paragraphBlock: Array<TParagraph>, conf
232242
/**
233243
* Take in a array of TParagraphs (block of lines), loop through and create events for the ones that should be events
234244
* Make changes to the paragraph lines and return all changed paragraphs as an array so they can be updated in one go
235-
* @param {Array<TParagraph>} block
245+
* @param {Array<TLine>} block
236246
* @param {{[string]:any}} config
237247
* @param {string} calendar - the calendar to use for the events or blank to ask
238-
* @returns {{paragraph:{TParagraph}, time:{Range++ object with start, end | null}}}
248+
* @returns {Promise<Array<TLine>>} - the lines that were turned into events, with their content rewritten
239249
*/
240-
export async function processTimeLines(paragraphBlock: Array<TParagraph>, config: EventBlocksConfig, calendar?: string = ''): Promise<Array<TParagraph>> {
250+
export async function processTimeLines<TLine: EventTextLine>(paragraphBlock: Array<TLine>, config: EventBlocksConfig, calendar?: string = ''): Promise<Array<TLine>> {
241251
// parseDateTextChecker()
242-
const timeLines = []
252+
const timeLines: Array<TLine> = []
243253
try {
244254
// First, we need to get all the data necessary to create this event, including user input
245255
// before we can show a status bar
@@ -315,7 +325,6 @@ export async function createEventPrompt(_heading?: string) {
315325
// parse event text
316326
const config = getPluginSettings()
317327
config.confirm = true
318-
// $FlowIgnore
319328
const timeLines = await processTimeLines([{ content: eventText, type: 'text' }], config)
320329
if (timeLines.length) {
321330
// Editor.updateParagraphs(timeLines)

0 commit comments

Comments
 (0)