Releases: mdelobelle/fileclass
Release list
0.2.6
Arc 4 is closed: every field type Fileclass can hold now has a short video on the page that documents it. This release carries what recording the last two takes turned up, plus one change of substance.
Changed
- A
JSONfield stores JSON. It used to parse your text and hand the structure to frontmatter, which Obsidian then wrote back as YAML — so nothing on disk was ever JSON, and the type was a notation for the editor alone. AJSONfield now stores the text, which Obsidian writes as a block scalar (import: |-), so a payload keeps the formatting it came with. Verified against Obsidian: a multi-line string is emitted as a block, a block already in the file survives a write to another key untouched, and what comes back is the exact text. The trade-off is the reason to have two types — YAML stores a real structure, which a base reaches into through a formula; JSON keeps the bytes and is opaque to Bases. A field already holding a mapping keeps working: it opens as pretty-printed JSON and becomes text on the next save - A declared raw field is not a warning. Obsidian paints a nested value it can't interpret in its warning colour, which is right for a value nobody can make sense of and wrong for a field a class declares and round-trips. The value itself stays raw on screen, which for these two types is the honest answer
Added
- Convert between the two notations. Changing a field's type doesn't rewrite what it holds, so a
JSONfield can open on YAML (and the reverse). The editor offers Convert from YAML — and the offer appears and disappears as you type, since it is only shown for text that reads as the other notation - A duration reads as a duration in the Properties panel.
PT45M44Sis the right thing on disk and unreadable on screen, so the human form is shown next to the stored value — never over it, since Obsidian's value there stays editable. A single value gets its reading beside it; an interval sequence gets one reading inside each pill, left of the remove button, so it names the value it reads
Fixed
- The raw editor stops losing work. Escape or the close button used to discard a blob of JSON or YAML in silence — the editor with the most typing in it was the last one without a guard. It shows Unsaved changes and asks now
- The parser answers while you type. An invalid document was only reported when you asked to save, so a mistake twenty lines up was learned about on the way out. The error, with its line, its column and a caret under the spot, appears as you type
- A field's edit button stays on the property's first line, instead of drifting to the middle row of a stacked list
- A structured value says how much is inside —
3 keys,5 items— where{…}said nothing
Learning the plugin
Two new takes finish the arc: a list of grouped fields (ObjectList, per-item ranks, a display template, and a base that counts the editions of each book) and when raw is the honest answer (YAML for structure you will query, JSON for bytes you want kept). Twenty-five videos now, fifty-eight minutes: https://mdelobelle.github.io/fileclass/videos/
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.5
Worth taking for the first fix: a control in Obsidian's Properties panel could act on a note you were no longer looking at.
Fixed
- A property control acts on the note in front of you. Obsidian owns the rows of its Properties panel and recycles them — switching notes keeps the element and rewrites its contents — and Fileclass rebuilt its button only when the property name changed. On a second note carrying the same property, the first note's button survived with that note captured inside it. With a list you could see it: one book's
editionsopened under another book's name, which is how it was found. With aCycleor aBooleanit was silent — the wrong note's value advanced, no modal, nothing on screen to give it away. The note and the field are now read from the row at the moment of the click, and the note's path and the field's type join the property name in the button's identity, so it is rebuilt rather than reused — which also stops an icon and a label from outliving the type they described - A child field may share a root field's name. A class keeps its nested children in the same list as its root fields, told apart by their path, and the resolver de-duplicated that list by name alone. A
Bookwith apublisherand aneditionslist whose items each have their own therefore lost the child: absent from the schema, and never offered when adding an item. A field is identified by its name at its level now. Overriding an inherited child still works, at its own level, andexcludesfollow the same rule — they name a field of a class, which is a root field; a group's children go with their parent - An item you start and abandon is no longer written. Add item on an
ObjectListpushed an empty item into the draft before opening its editor, and cancelling didn't take it back: nothing showed it — the list still read two rows, the Unsaved changes line stayed quiet — and the next Save wrote{}into the frontmatter, where it came back as a phantom item. An item exists once its editor is saved - An empty item reads as empty. With a display template, an item holding nothing rendered as the template's own separators — a lone
·, which reads as a value. Such an item now shows as (empty), and a list summarises it as2. (empty)rather than as a bare rank
Learning the plugin
One new take, on the type these fixes are about: a list of grouped fields — three editions of Dune typed as items of one property, a display template bringing each back to one line, the order changed by hand, and a base that counts them per book. The documentation gained what that last step had to be measured for: a base reaches a list through a formula — note.editions.length counts, note.editions[0].year reaches into an item — while mapping over the list renders an empty cell rather than an error.
Twenty-four videos now, fifty-five minutes: https://mdelobelle.github.io/fileclass/videos/
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.4
Eight fixes to the surfaces around nested properties, all found by playing the feature by hand before filming it rather than by a report.
Fixed
- A value that isn't a group is no longer thrown away. Give a field the
Objecttype and the value it already held — a plain string, saypublisher: Chilton Books— became invisible: the row showed nothing, validation called it fine, the editor opened empty, and the next save replaced it with{}without a word. It is now shown wherever values show, reported as a violation (must be a group of properties), displayed in the editor as Current value, not a group yet, and kept when you save an empty group — removing it takes an explicit Clear. Same forObjectList, whole and per item - A group's children are reachable from the field itself. Children was a button on the schema screen only, so the other doors into a field's definition — Alt-clicking its type icon, above all — couldn't get to them. The field's own settings carry the action now, and it appears as soon as you pick
ObjectorObjectListrather than after a save and a detour - A valid group is no longer painted as a warning. Obsidian can't interpret a nested property, so it colours the value as a warning — right for a value nobody can make sense of, wrong for a group a fileClass declares and validates. The colour is dropped when the field is an
Object/ObjectListand the value passes; a group that doesn't fit keeps it, because there the warning is the truth - A group's display template reaches Obsidian's Properties panel. A nested property showed there as raw JSON while every Fileclass surface showed the template's summary. The panel now shows that summary too, with the JSON in the tooltip. Obsidian types a mapping as
unknownand renders it read-only, so nothing editable is replaced - The breadcrumb names the group you are in. Editing the children of a nested group said Book › children at every depth, so two levels of nesting looked identical — and the children of a group are exactly where you need to know which group. It reads Comic › storage › shelf › children now
- The arrow keys move through a field list. Every row of the schema editor contributes four or five tab stops — fifty-five in a class of a dozen fields — so reaching the eighth field's Edit was thirty-odd presses of Tab. ↓ / ↑ move to the same action on the next field, → / ← between a field's actions, Home / End to the ends, and the whole list is a single tab stop. Moving down keeps the action, not the column: a group carries an extra Children button, so ↓ from Edit lands on Edit rather than sliding onto Remove. In the note-fields modal, the schema editor, a children list, and both value editors
- Closing a modal with unsaved changes asks instead of discarding. Nothing said whether Save was needed, so Escape or the close button threw a half-filled field definition away in silence. A modal holding a draft shows Unsaved changes at the left of its pinned footer the moment the draft differs from what it opened on — a long list can't scroll the warning out of sight — and closing offers Keep editing, Discard or Save. An untouched modal still closes without a word
- The first row's focus ring is no longer cut off. A modal's title is sticky and opaque, so it painted over the top of the ring on the first field — an overlap, not a clipping problem, which is why it only ever affected that one row
Learning the plugin
One new take, on the type these fixes are about: a group of fields inside a field — storage holding a room and a shelf, the shelf holding a unit and a level, a display template rebuilding the string a plain text field would have stored, and a base that sorts the comics by room and then by level, which is the half no string can do.
Twenty-three videos now, fifty-one minutes: https://mdelobelle.github.io/fileclass/videos/
The documentation's field pages also gained an outline in the right column that marks the section you're reading, and every field type in the table now links to its own section.
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.3
Four fixes to things you touch with the mouse, all found by playing a feature by hand before filming it rather than by a report.
Fixed
- Colour pickers open the way Obsidian's own does. Every colour control was an invisible
<input type="color">inside a<label>that activated it — and opening its popover from the settings window emptied the settings pane behind it, leaving the tab selected with nothing in it until you clicked it again. Obsidian's accent-colour setting, which behaves, is a plain visible input; ours are now the same thing, shaped into the same circles by CSS. Three places: the palette in Settings → Custom colors, a field's picker, and the canvas colour options - The icon picker shows the icon you already have. It renders 240 of some 1900 icons in alphabetical order, so a field holding
rocketopened on a screen starting ata-arrow-downwith nothing saying what the value was — you had to search for what you already had in order to see it. The current icon and its id now sit above the search box - The coordinates box reads what you actually paste. It accepted the canonical
lat,lonand nothing else, and said nothing when it refused: a Google or Apple Maps link, an OpenStreetMap link, ageo:URI, a degree-marked pair like48.8584° N, 2.2945° E, even a space between the two numbers all filled nothing at all. All of those are read now; text that holds no pair says so, and a pair that is off the globe is told apart from one that couldn't be read - The "Set next date" button had no label.
setIcon()on an Obsidian button replaces its content, so the text set just before it never rendered: the date picker showed an icon with no name, nothing on hover, nothing for a screen reader. It reads Set next date again
Learning the plugin
Five new takes, one per field type, on the pages that describe them: templated input, dates that link to your daily notes, icons, colours and your own palette, and a place on a map — the last one ending on the Maps plugin, where a Location field, an Icon field and a Color field turn out to be exactly the three properties a map marker needs.
Twenty-two videos now, forty-eight minutes: https://mdelobelle.github.io/fileclass/videos/
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.2
Two fixes to templated Input fields — the type that gives a value a fixed shape, {{room}} · {{unit}}-{{level}}. Both were found by playing the feature by hand before filming it, not by a report.
Fixed
- Editing one part of a templated value no longer wipes the others. The guided form opened with blank controls and re-rendered the whole template on any change, so correcting the level in
Study · A-3stored· -7and lost the room. A value already in the note is now read back into its parts — literals escaped, one capture per placeholder, a dropdown matched against its own choices — and a value that doesn't fit the template still leaves the controls empty, as before - The value you already had stays readable while you retype it. The preview is the value being built, and the first control you touch rewrites it — so for a value stored before the template existed, which fills no control, the preview was the only copy of it on screen. It now sits above the controls as Current value, selectable and never rewritten
Learning the plugin
A new take, A field with a fixed shape (2:53), opens the Input templates page: three books saying where they are shelved in three different ways, one template, and a library that ends up speaking one shape. https://www.youtube.com/watch?v=OmUgluPZal0
Eighteen videos now, thirty-nine minutes, one feature each: https://mdelobelle.github.io/fileclass/videos/
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.1
A patch release, and worth taking: two of these fixes are visible in Tour #1 itself. Follow the tour on 0.2.0, map a class to a folder, generate its base — and the view is empty. That is fixed, along with the reason it was empty.
Fixed
- A generated base returned nothing for a class bound by folder or tag. The managed view filtered on the class property alone —
fileClass == "Author"— and a note bound by Files paths or by a tag never carries that property. The filter now matches every binding it can express: the property, onefile.inFolder()per mapped folder, onefile.hasTag()per tag,or-ed together.inFolderrather than an equality on the folder because binding is by prefix: a note inAuthors/Deep/is bound too, and equality left it out. Bookmark groups and Base-view bindings have no Bases equivalent and stay outside the filter — the docs say which, instead of implying full coverage - A base generated before its class was mapped is repaired on the next sync — and the Sync button now knows it needs one. Mapping a class to a folder changes no field, so the status compared columns, found them equal, and reported Synced over a view returning nothing. It compares the filter too, computed from the options in the form, and the folder and tag settings refresh it as you type. A filter you edited yourself is never touched: it becomes yours, and sync leaves it alone
- A nested tag now binds to the class its parent tag maps. A note tagged
#author/frenchwas left untyped while a class mapped onauthorclaimed#author— and the generated view listed it anyway, because Bases'file.hasTag()includes children, as do Obsidian's tag search and tag pane. None of the Bases expressions can exclude children, so the two sides were aligned the other way: the resolver matches a tag and every tag it nests under, most specific first. This types notes that were not typed before — additive, nothing loses its typing — so a vault using nested tags will see more rows in its bases and more notes under validation - Switching Bases on after Fileclass no longer needs a restart. Feature detection ran once, at layout-ready, and nothing re-ran it: a vault where the core Bases plugin was enabled later kept File/Media candidates and generated views disabled for the whole session, with no way to tell why
- A generated base could report
Unknown view type: fileclass-table. The editable view is registered when Bases is available; a session that missed that moment rendered every base Fileclass had generated as an error — on a file Fileclass wrote itself. Registration is retried, and a failure is logged instead of being swallowed by a silentcatch - The
Templateoption said what it was, not what it wasn't. It read "compose each value from fixed parts" — which is exactly what someone defining a list of allowed values believes they want — and never mentionedSelect/Multi. Both the setting and the docs now name the two types that limit a field to values you choose, before explaining template syntax. That confusion cost a reader an hour and a half of goodwill; it was worth a sentence
Learning the plugin
The documentation home page now opens with the tour, the README links the series, and views.md describes exactly what the generated view filters on — including what it cannot.
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.2.0
A field's candidate list can now narrow itself by what the note already says — pick two things in the field's options and Fileclass writes the Bases formula and view for you. It was possible before, by hand, and it was expert-only: the first feature in this plugin to come from user feedback — asked for in this discussion, tracked as #19.
Fields & typed input
- Dependent candidates, without writing a formula (#19) — set Depends on another field and Match on property, and the picker is narrowed to the candidates matching this note's value. Fileclass adds the formula to the bound base and points the field at a narrowed copy of the view you chose, keeping its filters, sort and order. A preview shows both before you save. The comparison shape follows the source field's type — links by basename, everything else by value — and the
.isTruthy()guards are always there, without which an empty-vs-empty comparison is true and the picker offers every value-less candidate - Image values show as thumbnails — in the
Media/MultiMediapicker, and beside the value in the note-fields modal, the properties row and table cells. A media field points at a picture; every surface used to show its file name - Dates: a write format per type, and every format input proves itself —
Default date format,Default datetime formatandDefault time formatdecide what gets stored, each format field shows whatnow()becomes through it, and an unreadable format says which token it can't read - Date links can follow the date, and carry an alias —
Link pathaccepts{{YYYY}}-style tokens, soDaily/Notes/{{YYYY}}/{{MM}}/files each link under its year and month - Alt-click a date to advance it — a
Datewith a Next interval field applies its interval from any control, and while Alt is held the calendar icon becomes a skip-forward showing the date it would write. Next interval field is now a dropdown of the class's compatible fields instead of a typed name, which used to fail in silence - Number input: typing works, and it has − / + buttons — a native number input silently swallowed non-numeric keystrokes, leaving an empty field and no explanation. On an empty field the first − or + shows the minimum
- Removed: the
embedoption on media fields. It wrote![[cover.png]], which made sense in Metadata Menu — its fields could live inline in a note's body, where an embed renders. In frontmatter it renders nothing, and Obsidian doesn't register an embedded value as a link: a rename left it dangling while a plain link is rewritten for you, it is absent from the graph, and a Basesimagecolumn ignores it. Values already stored as embeds keep resolving everywhere Fileclass reads them
UI
- One gesture per field type, on every control — a
Cycleadvances, aBooleanflips, everything else opens its typed input, identically in the properties panel, the note-fields modal and a table cell. Alt-click always does the other one - A field's settings, one Alt-click from the note — Alt over a row's type icon in the note-fields modal turns it into a wrench; clicking it opens that field's definition editor, writing to the fileClass that declares it
- Reach a class's schema from a note bound to it (#23) — a wrench on the
fileClassrow of the properties panel, and one Open <class> schema entry per class in the note's context menu, including classes bound by tag, path or Base view, which leave no value to click - Long pickers are usable: a filter box focused on open (Enter flips the first match and clears it), an only-ticked view, Unselect all with its count, a whole row toggling wherever you click it, and off-screen rows skipped — on a 500-value list, a style recalc went from 24-43 ms to 8-13 ms and the worst scroll frame from 90 ms to 9 ms
- Two actions beside Obsidian's + Add property: + Add a class, and + Insert N missing fields when the note is missing any
- Three doors to a class, one screen — the breadcrumb in the note-fields modal, the indicator icon and the right-click menu all open the same schema editor, and it carries the class-level actions
- Create a class on the class-files folder's context menu, and binding a class now inserts its fields straight away (toggleable)
- Alt+Enter runs a modal's primary action from wherever the caret is, and list editors chain from the keyboard: adding a value puts the caret in it, Enter hands focus back to the Add button
Fixed
- The View and Display column suggesters stayed open after a choice while Base file closed — those two read their suggestions asynchronously, and the re-query that a selection triggers resolved after the popover had closed, reopening it
Set next dateignored the field's format, writing a bare ISO date — a field formattedYYYY-MM-DD ddd, or stored as a daily-note link, lost its shape as soon as the schedule advanced- Focus rings are no longer clipped in Fileclass's modals, and a values list reads as one block instead of a stack of unrelated settings
Learning the plugin
Sixteen short takes now cover the basics, one feature each, roughly two minutes apiece — install and setup, every simple field type, fields that point at notes, and the dependent candidates above. Each is embedded in the matching documentation page.
The whole series: https://www.youtube.com/playlist?list=PLLniwbD_l9kI
A longer Tour — the whole plugin end to end, from installing it to a typed library — is recorded against this release and lands shortly.
Compatibility: minAppVersion 1.12.7. Fileclass builds on the core Bases plugin, which needs to be enabled.
0.1.1
Views
- Generated bases scope the fileClass filter to the managed view, not base-wide (#55) — add a second view for another fileClass (e.g. a bookAuthor view in your book base) without it being shadowed. Migration-safe: existing bases are never rewritten.
Fields & typed input
- Base-sourced candidates & values follow the base view's order (#47) — File/MultiFile/Media/MultiMedia pickers and Select/Multi lists now appear in the view's own sort:/groupBy order instead of an arbitrary one
- Grouped candidate pickers (#47) — when the source view defines a groupBy, the picker mirrors those groups
UI
- In-app bulk field edit (#56) — new Fileclass: bulk edit a field command (and a fileClass note's right-click entry): pick a fileClass, an optional filter (a field condition or a base view) and a new value, preview every affected note with per-note toggles, then Apply (N) — dry-run by default
- Sticky modal titles everywhere, and sticky group headers in grouped pickers (#47)
Fixed
- contains is now a case-insensitive substring match (ILIKE '%value%', #56) — a contains condition on a MultiFile/MultiMedia field matches a stored [[Comic]] against comic instead of requiring the exact, same-case wikilink
Compatibility: minAppVersion 1.12.7.
Full Changelog: 0.1.0...0.1.1
0.1.0
Seven new field types / options + UI polish + a base fix — all frontmatter-only, no new runtime dependency.
Fields & typed input
templateoption onInput(#27) and theMultiInputtype (#28)Duration+CycleDurationwith presets and the date Set next date cycle (#30) — covers spaced-repetition scheduling; supersedes the droppedRecurrenceproposal (#29)Location(#31),Icon(#32),Color(#33) — with core Bases Map view interop (coordinates/icon/color)
UI
- Consistent Color/Icon value previews across the table, Properties editor, and note-fields modal (#44)
- User-editable custom color palette + custom colors in canvas field filters (#43)
- Sticky action footer so Save/Add stays visible in tall modals (#49)
Fixed
- Base columns for field names containing a space now render and edit correctly; existing bases self-heal on the next sync (#37)
Compatibility: minAppVersion 1.12.7.
🤖 Generated with Claude Code
0.0.4
What's Changed
- Chore/issue templates by @mdelobelle in #12
- fix: label sync via gh label create --force by @mdelobelle in #14
- fix: label sync via raw REST upsert by @mdelobelle in #15
- fix: quote label colors (yq float trap) by @mdelobelle in #16
- docs: document conditional link-field candidates by @mdelobelle in #17
- docs: lead with a concrete example (README + docs intro) by @mdelobelle in #21
- compat: lower minAppVersion to 1.12.7 by @mdelobelle in #24
- fix: resolve "From a note" value source tolerantly + path autocomplete (#20) by @mdelobelle in #25
Full Changelog: 0.0.3...0.0.4