@smartsoft001-mobilems/claude-plugins 2.112.0 → 2.114.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartsoft001-mobilems/claude-plugins",
3
- "version": "2.112.0",
3
+ "version": "2.114.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "mobilems",
3
3
  "description": "MobilEMS-specific Claude Code skills (MuzaCMS / MobileMS indexer API)",
4
- "version": "2.112.0"
4
+ "version": "2.114.0"
5
5
  }
@@ -55,18 +55,18 @@ list — re-implementing framework code is a defect, not a shortcut:
55
55
  2. [`packages/articles/README.md`](https://github.com/smartsoft001/mobilems-framework/blob/main/packages/articles/README.md) — this module's package catalog
56
56
  3. `libs/shared/angular/README.md` — the app's own shared lib (built by `mobilems-project-init`)
57
57
 
58
- | Do not hand-roll | Use |
59
- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
58
+ | Do not hand-roll | Use |
59
+ | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
60
60
  | The list page logic (first read from `?filter=`/persisted filter, persistence, sort/limit/page, search tab, read guard, list mode, list SEO) | `ArticlesCatalogBaseComponent` (`super({ defaults, persistKey, listPath, searchTab, seo })`) on `createCatalog`; cycle tags: `createArticleCycleTags(this.catalog)` |
61
- | The details page logic (SEO + SSR SEO, parent title, scroll, visit counter, widgets, authors, cycle tags) | `ArticleDetailsBaseComponent`; related module: `createArticleRelated(id)` |
62
- | Card logic (image, authors, tags, `?filter=` links) and `logVisit` / `related` HTTP calls | `ArticleCardBaseComponent`; `ArticlesService.logVisit` / `getRelated` |
63
- | A `Masonry` `useFactory` in the module | `provideBrowserMasonry()` |
64
- | a masonry grid (`new Masonry(...)`, per-page masonry JS/CSS) | `<smart-mobilems-masonry-grid>` (`MasonryGridComponent`) with a `#masonryContentTpl`; the `Masonry` provider only feeds it |
65
- | filter state / hand-built `query` arrays | `FiltersBaseComponent<Article>` + its `FiltersContext` accessors (`searchText`, `authors`, `cycles`, `publicationDateFrom/To`, `page`, `sort`, …) |
66
- | list/detail plumbing (facade wiring, id-from-route, PDF) | the `ArticlesListComponent` / `ArticlesItemComponent` base classes |
67
- | CMS preview logic (query params, credentialed fetch, states) | the `ArticlesPreviewComponent` base class — the app's `/article-preview` component is view-only |
68
- | media URLs, meta/OG tags, filter dictionaries, modals, WCAG | `FileUrlService`, `SeoService`/`MetaService`, `DictionaryService`, `ModalService`, `WcagService` |
69
- | a content-block renderer | `WidgetComponent` + the `ArticleWidgetType` map |
61
+ | The details page logic (SEO + SSR SEO, parent title, scroll, visit counter, widgets, authors, cycle tags) | `ArticleDetailsBaseComponent`; related module: `createArticleRelated(id)` |
62
+ | Card logic (image, authors, tags, `?filter=` links) and `logVisit` / `related` HTTP calls | `ArticleCardBaseComponent`; `ArticlesService.logVisit` / `getRelated` |
63
+ | A `Masonry` `useFactory` in the module | `provideBrowserMasonry()` |
64
+ | a masonry grid (`new Masonry(...)`, per-page masonry JS/CSS) | `<smart-mobilems-masonry-grid>` (`MasonryGridComponent`) with a `#masonryContentTpl`; the `Masonry` provider only feeds it |
65
+ | filter state / hand-built `query` arrays | `FiltersBaseComponent<Article>` + its `FiltersContext` accessors (`searchText`, `authors`, `cycles`, `publicationDateFrom/To`, `page`, `sort`, …) |
66
+ | list/detail plumbing (facade wiring, id-from-route, PDF) | the `ArticlesListComponent` / `ArticlesItemComponent` base classes |
67
+ | CMS preview logic (query params, credentialed fetch, states) | the `ArticlesPreviewComponent` base class — the app's `/article-preview` component is view-only |
68
+ | media URLs, meta/OG tags, filter dictionaries, modals, WCAG | `FileUrlService`, `SeoService`/`MetaService`, `DictionaryService`, `ModalService`, `WcagService` |
69
+ | a content-block renderer | `WidgetComponent` + the `ArticleWidgetType` map |
70
70
 
71
71
  Anything the framework genuinely lacks goes into `libs/shared/angular` **once** (and into its
72
72
  README) — never a per-module copy. `scripts/verify-module.sh` fails the run on hand-rolled masonry.
@@ -141,6 +141,6 @@ article-module-specific ones:
141
141
 
142
142
  - One run builds one named article module. Run the skill again — with a different name + template — for
143
143
  each additional content type the project needs.
144
- - Article modules reuse the foundation's generic `IArticleListItem` model (`@smartsoft001-mobilems/angular`) and the foundation's news carousel —
144
+ - Article modules reuse the foundation's generic `IArticleListItem` model (`@smartsoft001-mobilems/angular`) and the foundation's news carousel (`extends ArticlesCarouselBaseComponent`, museum template) —
145
145
  this skill does not rebuild them.
146
146
  - Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.
@@ -46,7 +46,7 @@ hardest:
46
46
  | filter/search state and `query` building | `FiltersContext` via `FiltersBaseComponent` (or `QueryFilterService` for plain query strings) |
47
47
  | confirm/cancel dialogs | `ModalService.open()` + `ModalRef` (and the shared `confirmation-modal` service) |
48
48
  | media URLs, meta/OG tags, dictionaries, WCAG, contrast | `FileUrlService`, `SeoService`/`MetaService`, `DictionaryService`, `WcagService`, `ContrastService` |
49
- | a calendar/date-picker helper duplicated per page | the shared lib's `calendar` component — built once, reused |
49
+ | a calendar/date-picker helper duplicated per page | the shared lib's `calendar` component (`extends CalendarBaseComponent`; the museum keeps its own template) — built once, reused |
50
50
 
51
51
  Anything the framework genuinely lacks goes into `libs/shared/angular` **once** (and into its
52
52
  README) — never a per-module copy. `scripts/verify-module.sh` fails the run on hand-rolled masonry.
@@ -83,7 +83,7 @@ README) — never a per-module copy. `scripts/verify-module.sh` fails the run on
83
83
  The cross-cutting rules live in `mobilems-project-init`
84
84
  `references/qa-hardening.md`; these are the objects-specific ones:
85
85
 
86
- - **Search debounce.** The panel full-text search (`app-objects-searchbar variant="panel"`) must
86
+ - **Search debounce.** The panel full-text search (`app-objects-searchbar variant="panel"`, a subclass of `SearchbarBaseComponent` with the museum's own template) must
87
87
  re-emit through a handler with `@debounce(250)` (`lodash-decorators`) — without it every keystroke
88
88
  hits the API. Collections and news filters already do this; keep the modules consistent.
89
89
  - **List page:** show the total result count (`facade.totalCount()`) and add the shared
@@ -20,8 +20,8 @@ libs/museum-objects/
20
20
  └── lib/
21
21
  ├── objects.module.ts # MuseumObjectsModule (references/module-and-routes.md)
22
22
  ├── objects.routes.ts
23
- ├── components/ # description, filter-input, high-def-request-modal,
24
- │ # menu, objects-searchbar, tabs/*
23
+ ├── components/ # description, filter-input (extends FilterInputBaseComponent), high-def-request-modal,
24
+ │ # menu, objects-searchbar (extends SearchbarBaseComponent), tabs/*
25
25
  ├── pages/ # list (ListComponent), item (ItemComponent) + index
26
26
  └── services/ # objects.service.ts + index
27
27
  ```
@@ -86,7 +86,8 @@ README) — never a per-module copy. `scripts/verify-module.sh` fails the run on
86
86
  ## Notes
87
87
 
88
88
  - Partners contributes nothing to `libs/shared/angular`: its grid/list cards live in its own lib, and
89
- the `partners-carousel` foundation component is already built by `mobilems-project-init`. So this
89
+ the `partners-carousel` foundation component (`extends PartnersCarouselBaseComponent`, with the
90
+ museum's own template) is already built by `mobilems-project-init`. So this
90
91
  skill builds only the partners module + its route — there is no shared-components reference.
91
92
  - This skill ONLY touches the partners module + its route. It never adds other feature modules,
92
93
  never re-runs the foundation, and never edits `libs/shared/angular`.
@@ -129,7 +129,7 @@ component that depends only on Angular + the framework packages + other foundati
129
129
  Run `python3 scripts/classify-shared-components.py` against the reference's
130
130
  `libs/shared/angular/src/lib/components` to list which shared components are FOUNDATION (build here)
131
131
  vs FEATURE-OWNED (built by a module skill, because they import a feature package). Build the
132
- foundation components (including the home-page carousels) + the app-only services/pipes/tools
132
+ foundation components (including the home-page carousels; their logic comes from the framework `…BaseComponent`s, the museum writes only the template) + the app-only services/pipes/tools
133
133
 
134
134
  - `configs.module.ts`, thread `<PREFIX>`, export them from the barrels, and build the `widget`
135
135
  container. Models, the common pipes/directives/services/tools and the objects filter models are
@@ -28,9 +28,9 @@ foundation deps — verified against the reference):
28
28
  - `@thisissoon/angular-masonry` + `masonry-layout` (masonry grids; `MasonryModule.forRoot()` in app.config;
29
29
  `masonry-layout` is also a peer of `@smartsoft001-mobilems/angular/bootstrap`, which registers it on
30
30
  `window` from `main.ts` — keep `allowedCommonJsDependencies: ["masonry-layout"]` in `apps/web/project.json`)
31
- - `swiper` (generic `slider` component)
32
- - `leaflet` + `@types/leaflet` (generic `map` component + `styles.scss` `leaflet.css` import)
33
- - `openseadragon` + `@types/openseadragon` (generic `gallery/gallery-fullscreen` deep-zoom)
31
+ - `swiper` (generic `slider` component — `extends SliderBaseComponent`, museum template)
32
+ - `leaflet` + `@types/leaflet` (generic `map` component `extends MapBaseComponent` and implements `loadLeaflet()`; the framework has no `leaflet` dependency; + `styles.scss` `leaflet.css` import)
33
+ - `openseadragon` + `@types/openseadragon` (generic `gallery/gallery-fullscreen` deep-zoom — `extends GalleryFullscreenDialogBaseComponent`, museum template)
34
34
  - `@angular/cdk` (`BreakpointObserver` in the home carousels; the `orientation` service)
35
35
  - `moment` + `moment-timezone` (date handling across shared components)
36
36
 
@@ -30,7 +30,9 @@ The shared library contains two kinds of shared component, separated by a simple
30
30
  This rule keeps the layering clean and lets the foundation library build on its own. The home-page
31
31
  carousels (`new-objects-carousel`, `news-carousel`, `partners-carousel`) and the home page are
32
32
  **foundation** shared components — they take `IObject` / `IArticleListItem` / `IPartner` from
33
- `@smartsoft001-mobilems/angular` and never import a feature package, so build them here.
33
+ `@smartsoft001-mobilems/angular` and never import a feature package, so build them here. Each one
34
+ extends its framework base (`NewObjectsCarouselBaseComponent`, `ArticlesCarouselBaseComponent`,
35
+ `PartnersCarouselBaseComponent`) and keeps its own template.
34
36
 
35
37
  ## Identify the foundation set
36
38
 
@@ -52,7 +54,14 @@ Build everything else — `header`, `footer`, `page`, the `filter*` family, `bre
52
54
  `pagination`, `searchbar`, `loader`, `error-retry`, `scroll-top`, `wcag`, `gallery`,
53
55
  `map`, `slider`, `carousel`, the three carousels above, `category-dropdown`, `dropdown`, `menu-item`,
54
56
  `next-page`, `calendar`, `confirmation-modal`, `newsletter-*`, `image-info-panel`, `icons`, `tabs`,
55
- and the `widget` container with its foundation widgets. The `app` shell and `skip-links` are
57
+ and the `widget` container with its foundation widgets. The logic of `calendar`, `pagination`,
58
+ `carousel`, the three home carousels, `slider`, `scroll-top`, `gallery` (+ fullscreen dialog),
59
+ `confirmation-modal`, `newsletter-modal`, `map`, the `filter-input` / `filter-date-input` /
60
+ `filter-custom-dictionary-input` / `filter-dictionary-input` family, `searchbar`, `catalog-toolbar`,
61
+ `catalog-filter-bar`, `theme-tags-filter` and `select-checkbox` is a framework base now (see
62
+ "Framework now → bases"): generate each as `extends …BaseComponent` (`scroll-top` extends `ScrollTopComponent`,
63
+ which has no `Base` suffix) and write only the museum's own template and styles — the framework
64
+ ships no templates. The `app` shell and `skip-links` are
56
65
  framework components (`smart-mobilems-app`, `smart-mobilems-skip-links`) — do not copy them.
57
66
 
58
67
  > Trust the script over this table for the **leaf** components (the grid/list cards and the
@@ -103,18 +112,22 @@ files duplicate exports that now exist; copying those is the single most common
103
112
 
104
113
  Framework now — do **not** generate (import from `@smartsoft001-mobilems/angular`):
105
114
 
106
- | Kind | Framework exports |
107
- | ------------ | ------------------------------------------------------------------------------------------------------------------ |
108
- | environment | `createMobilemsEnvironment`, `MOBILEMS_ENVIRONMENT`, `EnvironmentService` |
109
- | pipes | `altText`, `fileUrl`, `backgroundUrl`, `plainText`, `stripAnchors`, `capitalize` |
110
- | tools | `classifyLink`, `isInternalLink`, `normalizeUrl`, `stripHtml`, `formatNamedEntries`, `normalizeSearchText`, `newTabText`, `pageToOffset`, `decodeHtmlEntities` |
111
- | directives | `a[smartExternalLink]`, `[smartExternalLinks]`, `[smartFocusTrap]`, `[smartTruncatedTitle]` (references use `app…` — rename the attributes) |
112
- | services | `ConfirmationModalService`, `ExternalLinkConfirmationService`, `FilterPersistenceService`, `OrientationService`, `WcagChangesService`, `ContactService`, `DataService`, `MuseumSeoService` |
113
- | interceptors | `LanguageInterceptor`, `PreviewAuthInterceptor`, `SsrTimeoutInterceptor`, `DedupeRequestInterceptor` |
114
-
115
- What stays in the app lib: the confirmation-modal **component** (markup; it reads
116
- `ConfirmationModalService`), `truncateHtml`, the `line-height` service of the WCAG panel and any
117
- museum-only tools. `local-storage`, `configs-cache`, `not-found-content` are gone: language lives in
115
+ | Kind | Framework exports |
116
+ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
117
+ | environment | `createMobilemsEnvironment`, `MOBILEMS_ENVIRONMENT`, `EnvironmentService` |
118
+ | pipes | `altText`, `fileUrl`, `backgroundUrl`, `plainText`, `stripAnchors`, `capitalize` |
119
+ | tools | `classifyLink`, `isInternalLink`, `normalizeUrl`, `stripHtml`, `formatNamedEntries`, `normalizeSearchText`, `newTabText`, `pageToOffset`, `decodeHtmlEntities`, `ElementIdSequence`, `createSafeTimeouts`, `photoFileName`/`urlExtension`, `widgetImageUrl`, `overflowingTags`, `themeTagKey`, `themeTagsLayout`, `THEME_TAGS_VISIBLE_LIMIT` |
120
+ | directives | `a[smartExternalLink]`, `[smartExternalLinks]`, `[smartFocusTrap]`, `[smartTruncatedTitle]` (references use `app…` — rename the attributes) |
121
+ | services | `ConfirmationModalService`, `ExternalLinkConfirmationService`, `FilterPersistenceService`, `OrientationService`, `WcagChangesService`, `LineHeightService`, `BreadcrumbsService`, `ContactService`, `DataService`, `MuseumSeoService` |
122
+ | interceptors | `LanguageInterceptor`, `PreviewAuthInterceptor`, `SsrTimeoutInterceptor`, `DedupeRequestInterceptor` |
123
+ | bases | `CalendarBaseComponent`, `PaginationDotsBaseComponent`, `PaginationBaseComponent`, `CarouselBaseComponent`, `PartnersCarouselBaseComponent`, `NewObjectsCarouselBaseComponent`, `ArticlesCarouselBaseComponent`, `SliderBaseComponent` (+ `ISliderOptions`; `ScrollTopComponent` is server-guarded), `GalleryBaseComponent`, `GalleryFullscreenDialogBaseComponent` (`GalleryFullscreenBaseComponent` is `@deprecated`), `ConfirmationModalBaseComponent`, `NewsletterModalBaseComponent`, `MapBaseComponent`, `FilterInputBaseComponent`, `FilterDateInputBaseComponent`, `FilterCustomDictionaryInputBaseComponent`, `FilterDictionaryInputBaseComponent` (inline tree, `source`, paging), `ThemeTagsFilterBaseComponent`, `CatalogFilterBarBaseComponent`, `CatalogToolbarBaseComponent`, `SearchbarBaseComponent`, `SelectCheckboxBaseComponent` (+ `ISelectionHooks`) |
124
+ | SSR tools | `injectServerResponseInit`, `appendPreloadLinks` (image preload `Link` headers) |
125
+
126
+ What stays in the app lib: the **template and styles** of every base above — the museum keeps its
127
+ own HTML and Tailwind classes (the filter inputs, searchbar, catalog toolbar and filter bar, theme tags and select
128
+ checkbox are logic only — extend the base, write the markup yourself; e.g. the confirmation-modal component is markup over `ConfirmationModalBaseComponent` /
129
+ `ConfirmationModalService`), the `leaflet` dependency (`MapBaseComponent` asks the subclass for
130
+ `loadLeaflet()`), `truncateHtml` and any museum-only tools. `local-storage`, `configs-cache`, `not-found-content` are gone: language lives in
118
131
  the framework `TranslationService`, the config cache in `ConfigsFacade.init()`.
119
132
 
120
133
  Adjust to what the reference actually ships, but keep the rule: one implementation, exported from the
@@ -28,12 +28,12 @@ skeleton; build the foundation with `mobilems-project-init` first.
28
28
  `node_modules/@smartsoft001-mobilems/angular/README.md`)
29
29
  2. `libs/shared/angular/README.md` — the app's own shared lib
30
30
 
31
- | Do not hand-roll | Use |
32
- | --- | --- |
33
- | a tab strip | `TabsComponent` / `Tab` from the shared lib (the page already imports it) |
34
- | result cards | the module's own list-item components (`objects-list-item`, news/collection cards) |
35
- | "next page" behaviour | the shared `NextPageComponent`, same pattern as the module lists |
36
- | a search input | `app-objects-searchbar` / the shared searchbar variants |
31
+ | Do not hand-roll | Use |
32
+ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
33
+ | a tab strip | `TabsComponent` / `Tab` from the shared lib (the page already imports it) |
34
+ | result cards | the module's own list-item components (`objects-list-item`, news/collection cards) |
35
+ | "next page" behaviour | the shared `NextPageComponent`, same pattern as the module lists |
36
+ | a search input | `app-objects-searchbar` / the shared searchbar variants — the logic is `SearchbarBaseComponent`; the museum keeps its own template |
37
37
 
38
38
  Forking a result card for search is the classic mistake: the card then drifts
39
39
  from the module's list and the museum ends up with two visually different