Skip to content

Commit 1b6862d

Browse files
Merge pull request #1279 from CleverCloud/storybook/typecheck-related-libs
refactor(storybook): typecheck related libs
2 parents 2c41b48 + 3196927 commit 1b6862d

12 files changed

+107
-6
lines changed

.storybook/preview.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@ import { setCustomElementsManifest } from '@storybook/web-components';
22
// Any CSS file import automagically generates a `<link rel="stylesheet" href="bundledCssFile">` in the story iframe
33
import 'github-markdown-css/github-markdown.css';
44
import 'highlight.js/styles/vs.css';
5+
// @ts-ignore not worth helping TS understand this is valid since we don't need to type check this module
56
// eslint-disable-next-line import/no-unresolved
67
import customElementsManifest from '../dist/custom-elements.json';
78
import { AutodocsTemplate } from '../src/stories/lib/autodocs-template.jsx';
89
import '../src/stories/lib/i18n-control.js';
910
import '../src/styles/default-theme.css';
1011

12+
/**
13+
* @typedef {import('@storybook/web-components').Preview} Preview
14+
* @typedef {import('@storybook/addon-viewport').ViewportMap} ViewportMap
15+
*/
16+
1117
setCustomElementsManifest(customElementsManifest);
1218

19+
/** @type {Partial<ViewportMap>} */
1320
const viewports = {};
1421
Array.from(new Array(10)).map((_, i) => {
1522
const w = 350 + i * 100;
@@ -29,7 +36,7 @@ const availableLanguages = [
2936
{ value: 'missing', title: '🤬 Missing' },
3037
];
3138

32-
/** @type { import('@storybook/web-components').Preview } */
39+
/** @type {Preview} */
3340
const preview = {
3441
parameters: {
3542
docs: {

cem/generate-cem-vite-plugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @ts-ignore no types available for this dependency
12
import { cli } from '@custom-elements-manifest/analyzer/cli.js';
23

34
/**

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"@storybook/theming": "^8.4.5",
9595
"@storybook/web-components": "^8.4.5",
9696
"@storybook/web-components-vite": "^8.4.5",
97+
"@types/js-yaml": "^4.0.9",
9798
"@types/leaflet": "^1.9.12",
9899
"@types/leaflet.heat": "^0.2.4",
99100
"@types/statuses": "^2.0.5",

src/lib/i18n/i18n.types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export type Translations = { [key: string]: Translation };
44

55
export type Translation = string | TranslateFunction;
66

7-
export type TranslateFunction = (data: { [key: string]: any }) => Translated;
7+
export type TranslateFunction = (data: any) => Translated;
88

99
export type Translated = string | Node;
1010

src/stories/lib/make-story.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @ts-ignore not worth helping TS understand this is valid since we don't need to type check this module
12
// eslint-disable-next-line import/no-unresolved
23
import customElementsManifest from '../../../dist/custom-elements.json';
34
import { setLanguage } from '../../lib/i18n/i18n.js';

src/stories/lib/markdown-indexer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { readFile } from 'fs/promises';
22
import { getMetaDataFromMd } from './markdown-to-csf.js';
33

4-
/** @type {import ('@storybook/types').Indexer} */
4+
/** @type {import('storybook/internal/types').Indexer} */
55
export const markdownIndexer = {
66
test: /.md$/,
77
createIndex: async (fileName, { makeTitle }) => {
88
const markdownContent = await readFile(fileName, { encoding: 'utf-8' });
99

1010
const { title, subtitle } = getMetaDataFromMd(markdownContent);
1111

12-
/** @type {import('@storybook/types').IndexInput} */
12+
/** @type {import('storybook/internal/types').IndexInput} */
1313
const indexInput = {
1414
type: 'docs',
1515
importPath: fileName,

src/stories/lib/markdown-to-csf.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import { load as yamlLoad } from 'js-yaml';
22
import frontmatter from 'remark-frontmatter';
33
import remarkGfm from 'remark-gfm';
4+
// @ts-ignore no types available for this dependency
45
import highlight from 'remark-highlight.js';
56
import remark2Html from 'remark-html';
67
import remarkParse from 'remark-parse';
78
import unified from 'unified';
89

10+
/**
11+
* @typedef {import('vite').Plugin} Plugin
12+
*/
13+
14+
/**
15+
* A Vite plugin that transforms markdown files into Component Story Format (CSF).
16+
*
17+
* @returns {Plugin}
18+
*/
919
export function rollupMdToCsfPlugin() {
1020
return {
1121
name: 'markdown-to-csf',
@@ -25,6 +35,13 @@ const processor = unified()
2535
.use(highlight)
2636
.use(remark2Html, { sanitize: false });
2737

38+
/**
39+
* Converts markdown text into a Component Story Format (CSF) file with embedded documentation.
40+
* Processes the markdown into HTML and wraps it in a React component for display in Storybook.
41+
*
42+
* @param {string} markdownText
43+
* @returns {string} the CSF code with the markdown text embedded in a react component
44+
*/
2845
export function markdownToCsfWithDocsPage(markdownText) {
2946
const htmlContent = processor().processSync(markdownText).contents;
3047
const parsedHTML = JSON.stringify(htmlContent);
@@ -63,11 +80,20 @@ export function markdownToCsfWithDocsPage(markdownText) {
6380
return csfScript;
6481
}
6582

83+
/**
84+
* Extracts metadata from markdown content, including title and subtitle information
85+
* from frontmatter YAML and heading nodes.
86+
*
87+
* @param {string} markdownContent
88+
* @returns {{ title: string, subtitle: string }}
89+
*/
6690
export function getMetaDataFromMd(markdownContent) {
6791
const markdownAst = processor.parse(markdownContent);
6892

93+
// @ts-ignore the AST is not really typed
6994
const frontmatterNode = markdownAst.children.find((node) => node.type === 'yaml');
7095

96+
// @ts-ignore the AST is not really typed
7197
const headingNode = markdownAst.children.find((node) => node.type === 'heading' && node.depth === 1);
7298
const kind = getKind(frontmatterNode);
7399
const subtitle = getSubTitle(frontmatterNode, headingNode);
@@ -76,9 +102,17 @@ export function getMetaDataFromMd(markdownContent) {
76102
return { title, subtitle };
77103
}
78104

105+
/**
106+
* Extracts the subtitle from either the frontmatter YAML or the first heading.
107+
* Falls back to 'Untitled' if neither source contains a title.
108+
*
109+
* @param {{ value: string }|null} frontmatterNode
110+
* @param {{ children: Array<{ value: string }> }} headingNode
111+
* @returns {string} the extracted subtitle
112+
*/
79113
function getSubTitle(frontmatterNode, headingNode) {
80114
if (frontmatterNode != null) {
81-
const fmObject = yamlLoad(frontmatterNode.value);
115+
const fmObject = /** @type {{ title: string|null }} */ (yamlLoad(frontmatterNode.value));
82116
if (fmObject.title != null) {
83117
return fmObject.title;
84118
}
@@ -91,9 +125,16 @@ function getSubTitle(frontmatterNode, headingNode) {
91125
return 'Untitled';
92126
}
93127

128+
/**
129+
* Extracts the 'kind' metadata from the frontmatter YAML node.
130+
* Returns null if there is no kind specified.
131+
*
132+
* @param {{ value: string }|null} frontmatterNode - The frontmatter node containing YAML content
133+
* @returns {string|null} The extracted kind value or null if not found
134+
*/
94135
function getKind(frontmatterNode) {
95136
if (frontmatterNode != null) {
96-
const fmObject = yamlLoad(frontmatterNode.value);
137+
const fmObject = /** @type {{ kind: string }|null} */ (yamlLoad(frontmatterNode.value));
97138
if (fmObject.kind != null) {
98139
return fmObject.kind;
99140
}

src/stories/lib/smart-auth-plugin.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/**
2+
* @typedef {import('vite').Plugin} Plugin
3+
*/
4+
5+
/**
6+
* A Vite plugin that injects Clever Cloud Authentication tokens.
7+
* !! Caution: NEVER USE THIS PLUGIN FOR THE PROD BUILD !!
8+
*
9+
* @type {Plugin}
10+
*/
111
export const injectAuthForSmartComponentsPlugin = {
212
name: 'inject-auth-for-smart-components',
313
async transform(code, id) {

src/stories/lib/story-names.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/**
2+
* Formats a story name by applying various transformations:
3+
* - Capitalizes the first letter
4+
* - Adds spaces before numbers
5+
* - Converts CSS to uppercase
6+
* - Changes "with" phrases to parenthetical format
7+
*
8+
* @param {string} rawName - The raw story name to format
9+
* @returns {string} The formatted story name
10+
*/
111
function formatStoryName(rawName) {
212
return (
313
rawName[0].toUpperCase() +
@@ -13,6 +23,21 @@ function formatStoryName(rawName) {
1323
);
1424
}
1525

26+
/**
27+
* Enhances a story name by adding appropriate emoji prefixes based on the story type/state.
28+
* Processes special cases and adds visual indicators for different states:
29+
* - ⌛ for loading/waiting/skeleton states
30+
* - ➕ for adding states
31+
* - 📝 for editing states
32+
* - 🗑️ for deleting states
33+
* - 🕳 for empty states
34+
* - 👍 for loaded states
35+
* - 📈 for simulation states
36+
* - 🔥 for error states
37+
*
38+
* @param {string} defaultName - The original story name to enhance
39+
* @returns {string} The enhanced story name with appropriate prefix
40+
*/
1641
export function enhanceStoryName(defaultName) {
1742
if (defaultName === 'Default Story') {
1843
return 'Default';

0 commit comments

Comments
 (0)