mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 23:49:51 +00:00
Core: Respect title in images
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-core': patch
|
||||
---
|
||||
|
||||
[Remark Image] Respect `title` in images
|
||||
@@ -4,7 +4,7 @@ import type { Transformer } from 'unified';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import type { MdxjsEsm } from 'mdast-util-mdxjs-esm';
|
||||
import type { ISizeCalculationResult } from 'image-size/types/interface';
|
||||
import type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
||||
import type { MdxJsxAttribute, MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const VALID_BLUR_EXT = ['.jpeg', '.png', '.webp', '.avif', '.jpg'];
|
||||
@@ -94,6 +94,22 @@ export function remarkImage({
|
||||
src: Source,
|
||||
node: Image,
|
||||
): Promise<MdxJsxFlowElement | undefined> {
|
||||
const attributes: MdxJsxAttribute[] = [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'alt',
|
||||
value: node.alt ?? 'image',
|
||||
},
|
||||
];
|
||||
|
||||
if (node.title) {
|
||||
attributes.push({
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'title',
|
||||
value: node.title,
|
||||
});
|
||||
}
|
||||
|
||||
if (src.type === 'file' && useImport) {
|
||||
// Unique variable name for the given static image URL
|
||||
const variableName = `__img${importsToInject.length}`;
|
||||
@@ -112,37 +128,32 @@ export function remarkImage({
|
||||
importPath: getImportPath(src.file, file.dirname),
|
||||
});
|
||||
|
||||
attributes.push({
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'src',
|
||||
value: {
|
||||
type: 'mdxJsxAttributeValueExpression',
|
||||
value: variableName,
|
||||
data: {
|
||||
estree: {
|
||||
body: [
|
||||
{
|
||||
type: 'ExpressionStatement',
|
||||
expression: { type: 'Identifier', name: variableName },
|
||||
},
|
||||
],
|
||||
type: 'Program',
|
||||
sourceType: 'script',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const out: MdxJsxFlowElement = {
|
||||
children: [],
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'img',
|
||||
attributes: [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'alt',
|
||||
value: node.alt ?? 'image',
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'src',
|
||||
value: {
|
||||
type: 'mdxJsxAttributeValueExpression',
|
||||
value: variableName,
|
||||
data: {
|
||||
estree: {
|
||||
body: [
|
||||
{
|
||||
type: 'ExpressionStatement',
|
||||
expression: { type: 'Identifier', name: variableName },
|
||||
},
|
||||
],
|
||||
type: 'Program',
|
||||
sourceType: 'script',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
attributes,
|
||||
};
|
||||
|
||||
if (hasBlur) {
|
||||
@@ -167,32 +178,29 @@ export function remarkImage({
|
||||
|
||||
if (!size) return;
|
||||
|
||||
attributes.push(
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'src',
|
||||
// `src` doesn't support file paths, we can use `node.url` for files and let the underlying framework handle it
|
||||
value: src.type === 'url' ? src.url.toString() : node.url,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'width',
|
||||
value: size.width.toString(),
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'height',
|
||||
value: size.height.toString(),
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: 'img',
|
||||
attributes: [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'alt',
|
||||
value: node.alt ?? 'image',
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'src',
|
||||
// `src` doesn't support file paths, we can use `node.url` for files and let the underlying framework handle it
|
||||
value: src.type === 'url' ? src.url.toString() : node.url,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'width',
|
||||
value: size.width.toString(),
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'height',
|
||||
value: size.height.toString(),
|
||||
},
|
||||
],
|
||||
attributes,
|
||||
children: [],
|
||||
};
|
||||
}
|
||||
|
||||
+14
-13
@@ -180,12 +180,13 @@ export function createCore(options: CoreOptions) {
|
||||
if (out) config = out;
|
||||
}
|
||||
|
||||
workspaces = [];
|
||||
for (const workspace of Object.values(config.workspaces)) {
|
||||
const core = createCore(options);
|
||||
await core.init({ config: workspace.config });
|
||||
workspaces.push(core);
|
||||
}
|
||||
workspaces = await Promise.all(
|
||||
Object.values(config.workspaces).map(async (workspace) => {
|
||||
const core = createCore(options);
|
||||
await core.init({ config: workspace.config });
|
||||
return core;
|
||||
}),
|
||||
);
|
||||
},
|
||||
getOptions() {
|
||||
return options;
|
||||
@@ -221,22 +222,22 @@ export function createCore(options: CoreOptions) {
|
||||
EmitEntry[]
|
||||
> {
|
||||
const ctx = this.getPluginContext();
|
||||
const files: EmitEntry[] = [];
|
||||
async function add(v: Awaitable<EmitEntry[] | false>[]) {
|
||||
const files = new Map<string, EmitEntry>();
|
||||
async function add(...v: Awaitable<EmitEntry[] | false>[]) {
|
||||
for (const li of await Promise.all(v)) {
|
||||
if (li === false) continue;
|
||||
for (const item of li) files.push(item);
|
||||
for (const item of li) files.set(item.path, item);
|
||||
}
|
||||
}
|
||||
add(
|
||||
plugins.map((plugin) => {
|
||||
await add(
|
||||
...plugins.map((plugin) => {
|
||||
if (!filterPlugin(plugin) || !plugin.emit) return false;
|
||||
|
||||
return plugin.emit.call(ctx);
|
||||
}),
|
||||
...workspaces.map((workspace) => workspace.emit({ filterPlugin })),
|
||||
);
|
||||
add(workspaces.map((workspace) => workspace.emit({ filterPlugin })));
|
||||
return files;
|
||||
return Array.from(files.values());
|
||||
},
|
||||
async emitAndWrite(emitOptions?: EmitOptions): Promise<void> {
|
||||
const start = performance.now();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Core, Plugin, PluginContext } from '@/core';
|
||||
import type { Core, CoreOptions, Plugin, PluginContext } from '@/core';
|
||||
import type {
|
||||
LoadedConfig,
|
||||
CollectionItem,
|
||||
@@ -255,12 +255,18 @@ async function generateDynamicIndexFile({
|
||||
serverOptions,
|
||||
tc,
|
||||
}: FileGenContext) {
|
||||
const { configPath } = core.getOptions();
|
||||
const { configPath, environment, outDir } = core.getOptions();
|
||||
// serializable config options
|
||||
const partialOptions: CoreOptions = {
|
||||
configPath,
|
||||
environment,
|
||||
outDir,
|
||||
};
|
||||
codegen.lines.push(
|
||||
`import { dynamic } from 'fumadocs-mdx/runtime/dynamic';`,
|
||||
`import * as Config from '${codegen.formatImportPath(configPath)}';`,
|
||||
'',
|
||||
`const create = await dynamic<typeof Config, ${tc}>(Config, ${JSON.stringify(core.getOptions())}, ${JSON.stringify(serverOptions)});`,
|
||||
`const create = await dynamic<typeof Config, ${tc}>(Config, ${JSON.stringify(partialOptions)}, ${JSON.stringify(serverOptions)});`,
|
||||
);
|
||||
|
||||
async function generateCollectionObjectEntry(
|
||||
|
||||
Reference in New Issue
Block a user