npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pict-section-comments

v1.0.1

Published

Attach-to-anything comments section for Pict: threaded or flat discussions on any context (a record, a media item, a byte range in a file), with a pluggable data provider that defaults to in-memory AppData and a content spectrum from plain text to the ful

Readme

pict-section-comments

An attach-to-anything comments section for Pict. Mount it on any context (a record like Photo 278199, an uploaded media item, a vision, or a located slice of content such as a byte range in a file) and get threaded or flat discussions, a content spectrum from plain text up to markdown with image and file drag-in, newest or oldest sort, completable and collapsible threads, and a read-only mode.

The wrapping app overrides all reading and writing through one provider object. With nothing wired, the section runs on an in-memory provider backed by AppData, so it works the moment you mount it.

The model

Context  (OwnerType + IDOwner)      the broad subject: a Photo, a Media item, a Vision, a file
  -> Thread  (optional Anchor, Status)   the official discussion, or a note pinned to a location
       -> Comment  (optional one reply level, ContentType)
  • A Context is { OwnerType, IDOwner }, the same polymorphic-owner shape used elsewhere in Retold (for example Media). One context holds many threads.
  • A Thread is either the official discussion on the whole context (no anchor) or a note pinned to a sub-location. The optional Anchor is an opaque locator the host defines, for example { Type: 'ByteRange', Start: 100, End: 500 }, { Type: 'Paragraph', Selector: '...' }, or { Type: 'Point', X, Y }. The section stores and round-trips it, shows a small badge, and fires onAnchorActivate(anchor) so the host can scroll or highlight its own content. A thread carries a Status (Open, Resolved, Completed); resolved and completed threads can collapse.
  • A Comment has an author, a body, and a ContentType (text, markdown, rich, json). In threaded mode a comment can carry one level of replies (ParentKey).

Quick start

const libComments = require('pict-section-comments');

pict.addView('WorkItem-Comments', Object.assign({}, libComments.default_configuration,
{
    Context: { OwnerType: 'WorkItem', IDOwner: 4012 },
    CurrentUser: { Key: 7, Name: 'Ada Lovelace' },
    EditorMode: 'markdown',
    Threaded: true
}), libComments);

pict.views['WorkItem-Comments'].render();   // in-memory by default

Mount more than one on a page by registering them under different hashes; each keeps its own state.

Overriding reading and writing

The section never touches storage itself. It calls a provider that implements this interface (every method returns a Promise):

listThreads(pContext)          -> Thread[]
createThread(pThreadDraft)     -> Thread
updateThread(pKey, pPatch)     -> Thread     // Status (resolve / complete / reopen), Title, Anchor, Sort
deleteThread(pKey)             -> void
listComments(pThreadKey)       -> Comment[]
createComment(pCommentDraft)   -> Comment
updateComment(pKey, pPatch)    -> Comment     // edit Body
deleteComment(pKey)            -> void

Pass your own object as DataProvider and the section talks to your backend:

pict.addView('WorkItem-Comments', Object.assign({}, libComments.default_configuration,
{
    Context: { OwnerType: 'WorkItem', IDOwner: 4012 },
    DataProvider: myServerBackedCommentProvider   // implements the interface above
}), libComments);

CommentDataProvider (exported) is a base class with the four list and create primitives left abstract; it implements loadContext, resolveThread, completeThread, and reopenThread on top of them, so a subclass only fills in the primitives. InMemoryCommentProvider (the default) is a full reference implementation; pass it a Store object (for example a slice of AppData) to keep its state observable and serializable.

Content modes

EditorMode sets the composer and the default ContentType for new comments:

  • text and multiline: a plain box; bodies render escaped, with line breaks preserved.
  • markdown: a markdown composer with image and file drag-in (drop or paste, routed to the ImageUpload hook), rendered read-only through pict-section-content (code, tables, Mermaid, KaTeX). This is the everyday rich comment.
  • rich: the full pict-section-markdowneditor (CodeMirror 6), opened in a modal for composing, rendered read-only through pict-section-content. The host supplies CodeMirror: pass the CodeMirrorModules option ({ EditorView, EditorState, extensions, ... }) or set window.CodeMirrorModules. Without it, rich falls back to the markdown composer, so it never breaks. The demo bundles CodeMirror to show this mode.
  • json: reserved for structured bodies (diagrams, svg); rendered escaped for now, a registered adapter renders it later.

Bodies are escaped or sanitized before display, so user content cannot inject markup.

Configuration

| Option | Default | Meaning | |---|---|---| | Context | {} | The { OwnerType, IDOwner } this instance is bound to (required). | | DataProvider | in-memory | The object that reads and writes. Omit to use AppData. | | Threaded | true | One level of replies when true; a flat list when false. | | EditorMode | markdown | text, multiline, markdown, or rich. | | ReadOnly | false | Render-only: no composer, no actions. | | SortOrder | oldest | oldest or newest; user-toggleable in the header. | | CollapseCompleted | true | Resolved and completed threads start collapsed. | | AllowNewThread / AllowResolve / AllowReply / AllowEdit / AllowDelete | true | Permission gates. | | CurrentUser | { Name: 'Anonymous' } | Author of new comments; { Key, Name, Avatar }. | | ImageUpload | none | function (pFile, fCallback(pError, pURL)) for drag-in. | | CodeMirrorModules | none | CodeMirror 6 modules for the rich editor; also read from window.CodeMirrorModules. | | Title / EmptyText | | Header label and empty-state copy. |

Event callbacks (all optional): onThreadCreated, onThreadResolved, onCommentAdded, onCommentEdited, onCommentDeleted, onAnchorActivate, onChange.

Edit and delete are gated to the comment's author when CurrentUser.Key is set; with no key set (single-user or demo) both are allowed. Delete confirms through pict-section-modal.

Run the demo and the tests

npm install --legacy-peer-deps
npm test                 # the Mocha suite (provider, content adapter, view shaping)
npm run build            # the section bundle in dist/

npm run build:codemirror # bundles CodeMirror for the demo's rich mode (one time)
cd example_applications/comments_demo
npm run build            # an in-memory demo; serve dist/ and open index.html

The demo has a Markdown / Rich toggle: Markdown composes inline, Rich opens the full editor in a modal.

License

MIT.