datocms-plugin-alt-text-ai 0.5.2 → 0.5.5
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/README.md +12 -1
- package/dist/assets/index-B_BYnrd4.css +1 -0
- package/dist/assets/index-RZCW53qo.js +16 -0
- package/dist/index.html +13 -0
- package/package.json +26 -36
- package/build/asset-manifest.json +0 -13
- package/build/index.html +0 -1
- package/build/static/css/main.8467dedd.css +0 -2
- package/build/static/css/main.8467dedd.css.map +0 -1
- package/build/static/js/main.d6fa325c.js +0 -3
- package/build/static/js/main.d6fa325c.js.LICENSE.txt +0 -56
- package/build/static/js/main.d6fa325c.js.map +0 -1
- package/public/index.html +0 -11
- package/public/robots.txt +0 -3
- package/src/entrypoints/AltTextAIButton.tsx +0 -129
- package/src/entrypoints/ConfigScreen.tsx +0 -66
- package/src/entrypoints/styles.module.css +0 -7
- package/src/index.tsx +0 -27
- package/src/react-app-env.d.ts +0 -1
- package/src/utils/render.tsx +0 -9
- package/tsconfig.json +0 -26
- /package/{build → dist}/robots.txt +0 -0
package/public/index.html
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
</head>
|
|
7
|
-
<body>
|
|
8
|
-
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
9
|
-
<div id="root"></div>
|
|
10
|
-
</body>
|
|
11
|
-
</html>
|
package/public/robots.txt
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { Client, buildClient } from "@datocms/cma-client-browser";
|
|
2
|
-
import {
|
|
3
|
-
type FileFieldValue,
|
|
4
|
-
RenderFieldExtensionCtx,
|
|
5
|
-
} from "datocms-plugin-sdk";
|
|
6
|
-
import { Button, Canvas, Spinner } from "datocms-react-ui";
|
|
7
|
-
import { isArray } from "lodash";
|
|
8
|
-
import get from "lodash/get";
|
|
9
|
-
import { useState } from "react";
|
|
10
|
-
|
|
11
|
-
type PropTypes = {
|
|
12
|
-
ctx: RenderFieldExtensionCtx;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
async function fetchAlt(apiKey: string, client: Client, asset: FileFieldValue) {
|
|
16
|
-
const { url } = await client.uploads.find(asset.upload_id);
|
|
17
|
-
|
|
18
|
-
// Instead of sending over files that are possibly too big or the wrong format, etc.,
|
|
19
|
-
// we'll use Imgix to pre-transform them into a valid format and smaller size
|
|
20
|
-
let transformedUrl = new URL(url);
|
|
21
|
-
transformedUrl.searchParams.set("fm", "jpeg");
|
|
22
|
-
transformedUrl.searchParams.set("w", "1024");
|
|
23
|
-
|
|
24
|
-
const result = await (
|
|
25
|
-
await fetch("https://alttext.ai/api/v1/images", {
|
|
26
|
-
method: "POST",
|
|
27
|
-
headers: {
|
|
28
|
-
"Content-Type": "application/json",
|
|
29
|
-
"X-API-Key": apiKey ?? "",
|
|
30
|
-
},
|
|
31
|
-
body: JSON.stringify({
|
|
32
|
-
image: {
|
|
33
|
-
url: transformedUrl.toString(),
|
|
34
|
-
},
|
|
35
|
-
}),
|
|
36
|
-
})
|
|
37
|
-
).json();
|
|
38
|
-
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function generateAlts(
|
|
43
|
-
currentFieldValue: unknown,
|
|
44
|
-
ctx: RenderFieldExtensionCtx,
|
|
45
|
-
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
|
|
46
|
-
) {
|
|
47
|
-
if (!ctx.currentUserAccessToken) {
|
|
48
|
-
await ctx.alert(
|
|
49
|
-
"This plugin needs the currentUserAccessToken to function. Please give it that permission and try again.",
|
|
50
|
-
);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
setIsLoading(true);
|
|
55
|
-
try {
|
|
56
|
-
const client = buildClient({ apiToken: ctx.currentUserAccessToken || "" });
|
|
57
|
-
const isGallery = isArray(currentFieldValue);
|
|
58
|
-
if (isGallery) {
|
|
59
|
-
const existingAssets = currentFieldValue as FileFieldValue[];
|
|
60
|
-
const newAssets = [];
|
|
61
|
-
for (const asset of existingAssets) {
|
|
62
|
-
console.log("asset", asset);
|
|
63
|
-
const result = await fetchAlt(
|
|
64
|
-
ctx.plugin.attributes.parameters.apiKey as string,
|
|
65
|
-
client,
|
|
66
|
-
asset,
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
if (result.error_code) {
|
|
70
|
-
ctx.alert(
|
|
71
|
-
`Alt text error for <a href="/media/assets/${asset.upload_id}" target="_blank">image ${asset.upload_id}</a>: <code>${result.error_code}: ${result.errors?.base?.[0] ?? ""}</code>`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
asset.alt = result.alt_text;
|
|
76
|
-
newAssets.push(asset);
|
|
77
|
-
}
|
|
78
|
-
ctx.setFieldValue(ctx.fieldPath, newAssets);
|
|
79
|
-
} else {
|
|
80
|
-
const assetValue = currentFieldValue as FileFieldValue;
|
|
81
|
-
|
|
82
|
-
const result = await fetchAlt(
|
|
83
|
-
ctx.plugin.attributes.parameters.apiKey as string,
|
|
84
|
-
client,
|
|
85
|
-
assetValue,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
if (result.error_code) {
|
|
89
|
-
await ctx.alert(
|
|
90
|
-
`Error fetching alt text: <code>${result.error_code}: ${result.errors?.base?.[0] ?? ""}</code>`,
|
|
91
|
-
);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
assetValue.alt = result.alt_text;
|
|
96
|
-
ctx.setFieldValue(ctx.fieldPath, assetValue);
|
|
97
|
-
}
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.log(error);
|
|
100
|
-
} finally {
|
|
101
|
-
setIsLoading(false);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const AltTextAIButton = ({ ctx }: PropTypes) => {
|
|
106
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
107
|
-
const currentFieldValue = get(ctx.formValues, ctx.fieldPath);
|
|
108
|
-
const isGallery = isArray(currentFieldValue);
|
|
109
|
-
const isGalleryWithItems =
|
|
110
|
-
isArray(currentFieldValue) && currentFieldValue.length;
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<Canvas ctx={ctx}>
|
|
114
|
-
{(isGalleryWithItems || (!isGallery && !!currentFieldValue)) && (
|
|
115
|
-
<Button
|
|
116
|
-
fullWidth
|
|
117
|
-
disabled={isLoading}
|
|
118
|
-
onClick={() => {
|
|
119
|
-
generateAlts(currentFieldValue, ctx, setIsLoading);
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
122
|
-
Generate Alt Text {isLoading && <Spinner size={24} />}
|
|
123
|
-
</Button>
|
|
124
|
-
)}
|
|
125
|
-
</Canvas>
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export default AltTextAIButton;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { RenderConfigScreenCtx } from 'datocms-plugin-sdk';
|
|
2
|
-
import {
|
|
3
|
-
Button,
|
|
4
|
-
Canvas,
|
|
5
|
-
ContextInspector,
|
|
6
|
-
Spinner,
|
|
7
|
-
TextField,
|
|
8
|
-
} from 'datocms-react-ui';
|
|
9
|
-
import s from './styles.module.css';
|
|
10
|
-
import { useState } from 'react';
|
|
11
|
-
|
|
12
|
-
type Props = {
|
|
13
|
-
ctx: RenderConfigScreenCtx;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
async function saveApiKey(
|
|
17
|
-
ctx: RenderConfigScreenCtx,
|
|
18
|
-
apiKey: string,
|
|
19
|
-
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>
|
|
20
|
-
) {
|
|
21
|
-
setIsLoading(true);
|
|
22
|
-
await ctx.updatePluginParameters({ apiKey });
|
|
23
|
-
setIsLoading(false);
|
|
24
|
-
ctx.customToast({
|
|
25
|
-
type: 'notice',
|
|
26
|
-
message: 'API Key Saved!',
|
|
27
|
-
dismissOnPageChange: true,
|
|
28
|
-
dismissAfterTimeout: 5000,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export default function ConfigScreen({ ctx }: Props) {
|
|
33
|
-
const [apiKey, setApiKey] = useState(
|
|
34
|
-
(ctx.plugin.attributes.parameters.apiKey as string) ?? ''
|
|
35
|
-
);
|
|
36
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Canvas ctx={ctx}>
|
|
40
|
-
<div className={s.form}>
|
|
41
|
-
<TextField
|
|
42
|
-
required
|
|
43
|
-
name="altTextAPIKey"
|
|
44
|
-
id="altTextAPIKey"
|
|
45
|
-
label="Alt Text API Key"
|
|
46
|
-
value={apiKey}
|
|
47
|
-
onChange={(newValue) => setApiKey(newValue)}
|
|
48
|
-
/>
|
|
49
|
-
<p>
|
|
50
|
-
You can get your API key by going to{' '}
|
|
51
|
-
<a href="https://alttext.ai/account/api_keys" target="_blank">
|
|
52
|
-
https://alttext.ai/account/api_keys
|
|
53
|
-
</a>
|
|
54
|
-
</p>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<Button
|
|
58
|
-
disabled={isLoading}
|
|
59
|
-
fullWidth
|
|
60
|
-
onClick={() => saveApiKey(ctx, apiKey, setIsLoading)}
|
|
61
|
-
>
|
|
62
|
-
Save {isLoading && <Spinner size={24} />}
|
|
63
|
-
</Button>
|
|
64
|
-
</Canvas>
|
|
65
|
-
);
|
|
66
|
-
}
|
package/src/index.tsx
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { render } from './utils/render';
|
|
2
|
-
import ConfigScreen from './entrypoints/ConfigScreen';
|
|
3
|
-
import 'datocms-react-ui/styles.css';
|
|
4
|
-
import { connect, Field, RenderFieldExtensionCtx } from 'datocms-plugin-sdk';
|
|
5
|
-
import AltTextAIButton from './entrypoints/AltTextAIButton';
|
|
6
|
-
|
|
7
|
-
connect({
|
|
8
|
-
renderConfigScreen(ctx) {
|
|
9
|
-
return render(<ConfigScreen ctx={ctx} />);
|
|
10
|
-
},
|
|
11
|
-
overrideFieldExtensions(field: Field) {
|
|
12
|
-
if (
|
|
13
|
-
field.attributes.field_type === 'gallery' ||
|
|
14
|
-
field.attributes.field_type === 'file'
|
|
15
|
-
) {
|
|
16
|
-
return {
|
|
17
|
-
addons: [{ id: 'altTextAI' }],
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
renderFieldExtension(fieldExtensionId: string, ctx: RenderFieldExtensionCtx) {
|
|
22
|
-
switch (fieldExtensionId) {
|
|
23
|
-
case 'altTextAI':
|
|
24
|
-
return render(<AltTextAIButton ctx={ctx} />);
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
});
|
package/src/react-app-env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="react-scripts" />
|
package/src/utils/render.tsx
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React, { StrictMode } from 'react';
|
|
2
|
-
import { createRoot } from 'react-dom/client';
|
|
3
|
-
|
|
4
|
-
const container = document.getElementById('root');
|
|
5
|
-
const root = createRoot(container!);
|
|
6
|
-
|
|
7
|
-
export function render(component: React.ReactNode): void {
|
|
8
|
-
root.render(<StrictMode>{component}</StrictMode>);
|
|
9
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es5",
|
|
4
|
-
"lib": [
|
|
5
|
-
"dom",
|
|
6
|
-
"dom.iterable",
|
|
7
|
-
"esnext"
|
|
8
|
-
],
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"allowSyntheticDefaultImports": true,
|
|
13
|
-
"strict": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"noFallthroughCasesInSwitch": true,
|
|
16
|
-
"module": "esnext",
|
|
17
|
-
"moduleResolution": "node",
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"isolatedModules": true,
|
|
20
|
-
"noEmit": true,
|
|
21
|
-
"jsx": "react-jsx"
|
|
22
|
-
},
|
|
23
|
-
"include": [
|
|
24
|
-
"src"
|
|
25
|
-
]
|
|
26
|
-
}
|
|
File without changes
|