@actuate-media/plugin-ai 0.5.4 → 0.5.6
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/CHANGELOG.md +25 -0
- package/dist/__tests__/hooks-embedding-noprovider.test.d.ts +2 -0
- package/dist/__tests__/hooks-embedding-noprovider.test.d.ts.map +1 -0
- package/dist/__tests__/hooks-embedding-noprovider.test.js +32 -0
- package/dist/__tests__/hooks-embedding-noprovider.test.js.map +1 -0
- package/dist/__tests__/hooks.test.d.ts +2 -0
- package/dist/__tests__/hooks.test.d.ts.map +1 -0
- package/dist/__tests__/hooks.test.js +124 -0
- package/dist/__tests__/hooks.test.js.map +1 -0
- package/dist/__tests__/plugin-config.test.d.ts +2 -0
- package/dist/__tests__/plugin-config.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-config.test.js +104 -0
- package/dist/__tests__/plugin-config.test.js.map +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +10 -3
- package/dist/hooks.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @actuate-media/plugin-ai
|
|
2
2
|
|
|
3
|
+
## 0.5.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- daf91b4: Fix accessibility scoring penalizing every image as missing alt text.
|
|
8
|
+
|
|
9
|
+
The afterUpdate content-scoring hook parsed images with a single regex whose
|
|
10
|
+
greedy `[^>]*` consumed the rest of the `<img>` tag before the optional
|
|
11
|
+
`alt="…"` group, so `alt` was never captured and every image — even ones with
|
|
12
|
+
valid alt text — was scored as missing-alt. Each tag's `src`/`alt` are now
|
|
13
|
+
extracted independently, so present alt text is credited correctly.
|
|
14
|
+
|
|
15
|
+
## 0.5.5
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- e25cd48: Standardize React peer ranges to `^18.0.0 || ^19.0.0`.
|
|
20
|
+
|
|
21
|
+
Plugin React peer ranges were inconsistent: `plugin-ai`, `plugin-commerce`, and
|
|
22
|
+
`plugin-seo` pinned `react: ^19.2.0` (excluding React 18, which `cms-core`
|
|
23
|
+
supports via `react >=18.0.0`), while the others used `^18.0.0 || ^19.2.0`
|
|
24
|
+
(excluding React 19.0/19.1). Either produced an `ERESOLVE` install failure for
|
|
25
|
+
consumers on the excluded versions. All bundled plugins now declare `react`
|
|
26
|
+
(and `react-dom` where already peered) as `^18.0.0 || ^19.0.0`.
|
|
27
|
+
|
|
3
28
|
## 0.5.4
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-embedding-noprovider.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hooks-embedding-noprovider.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { getAIProvider } from '../providers/index.js';
|
|
3
|
+
import { aiHooks } from '../hooks.js';
|
|
4
|
+
/**
|
|
5
|
+
* This suite lives in its own file so the global AI provider singleton
|
|
6
|
+
* (providers/index.ts) is guaranteed to start as null: vitest isolates module
|
|
7
|
+
* state per test file, and there is no public API to reset the singleton back to
|
|
8
|
+
* null once set. Do NOT call setAIProvider / aiPlugin({ provider, apiKey }) here.
|
|
9
|
+
*/
|
|
10
|
+
const afterCreate = aiHooks[1];
|
|
11
|
+
function docPayload(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
id: 'doc_1',
|
|
14
|
+
collection: 'articles',
|
|
15
|
+
slug: 'my-article',
|
|
16
|
+
status: 'published',
|
|
17
|
+
data: {},
|
|
18
|
+
...overrides,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
describe('aiHooks afterCreate — no provider configured', () => {
|
|
22
|
+
it('starts with no global AI provider', () => {
|
|
23
|
+
expect(getAIProvider()).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
it('is a safe no-op (no throw, no _embedding) when no provider is configured', async () => {
|
|
26
|
+
expect(getAIProvider()).toBeNull();
|
|
27
|
+
const payload = docPayload({ data: { body: 'x' } });
|
|
28
|
+
await expect(afterCreate.handler(payload)).resolves.toBeUndefined();
|
|
29
|
+
expect(payload.data._embedding).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=hooks-embedding-noprovider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-embedding-noprovider.test.js","sourceRoot":"","sources":["../../src/__tests__/hooks-embedding-noprovider.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAErC;;;;;GAKG;AAEH,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAE,CAAA;AAE/B,SAAS,UAAU,CAAC,YAAgD,EAAE;IACpE,OAAO;QACL,EAAE,EAAE,OAAO;QACX,UAAU,EAAE,UAAU;QACtB,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,EAAE;QACR,GAAG,SAAS;KACb,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;QAElC,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;QACnD,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAA;QACnE,MAAM,CAAE,OAAO,CAAC,IAA4B,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,CAAA;IAC1E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hooks.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { setAIProvider } from '../providers/index.js';
|
|
3
|
+
import { aiHooks } from '../hooks.js';
|
|
4
|
+
// aiHooks[0] is the afterUpdate scorer; aiHooks[1] is the afterCreate embedder.
|
|
5
|
+
const afterUpdate = aiHooks[0];
|
|
6
|
+
const afterCreate = aiHooks[1];
|
|
7
|
+
function docPayload(overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'doc_1',
|
|
10
|
+
collection: 'articles',
|
|
11
|
+
slug: 'my-article',
|
|
12
|
+
status: 'published',
|
|
13
|
+
data: {},
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A fake AIProvider matching the shape used in content-generator.test.ts /
|
|
19
|
+
* media-vision.test.ts. `generateEmbedding` is customizable so individual tests
|
|
20
|
+
* can return a known vector, record the text argument, or reject.
|
|
21
|
+
*/
|
|
22
|
+
function makeProvider(generateEmbedding) {
|
|
23
|
+
return {
|
|
24
|
+
async generateText() {
|
|
25
|
+
return { text: '', usage: { promptTokens: 0, completionTokens: 0 } };
|
|
26
|
+
},
|
|
27
|
+
generateEmbedding,
|
|
28
|
+
async *streamText() {
|
|
29
|
+
yield '';
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
describe('aiHooks afterUpdate — AI score computation', () => {
|
|
34
|
+
it('registers for the base afterUpdate event', () => {
|
|
35
|
+
expect(afterUpdate.event).toBe('afterUpdate');
|
|
36
|
+
});
|
|
37
|
+
it('attaches a composite _aiScore { overall, breakdown, grade } computed from the body', async () => {
|
|
38
|
+
const payload = docPayload({
|
|
39
|
+
data: {
|
|
40
|
+
title: 'A clear title',
|
|
41
|
+
metaDescription: 'A'.repeat(130),
|
|
42
|
+
body: '<h2>Intro</h2><p>Simple readable sentences about coffee.</p>',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
await afterUpdate.handler(payload);
|
|
46
|
+
const score = payload.data._aiScore;
|
|
47
|
+
expect(score).toBeDefined();
|
|
48
|
+
expect(typeof score.overall).toBe('number');
|
|
49
|
+
expect(score.overall).toBeGreaterThanOrEqual(0);
|
|
50
|
+
expect(score.overall).toBeLessThanOrEqual(100);
|
|
51
|
+
expect(score.grade).toMatch(/^[A-F]$/);
|
|
52
|
+
// The three dimensions the hook actually feeds into the composite.
|
|
53
|
+
expect(score.breakdown).toHaveProperty('readability');
|
|
54
|
+
expect(score.breakdown).toHaveProperty('seo');
|
|
55
|
+
expect(score.breakdown).toHaveProperty('accessibility');
|
|
56
|
+
});
|
|
57
|
+
it('is a no-op when the document has no body (empty data object)', async () => {
|
|
58
|
+
const payload = docPayload({ data: {} });
|
|
59
|
+
await expect(afterUpdate.handler(payload)).resolves.toBeUndefined();
|
|
60
|
+
expect(payload.data._aiScore).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
it('is a no-op (no throw) when data is null', async () => {
|
|
63
|
+
const payload = docPayload({ data: null });
|
|
64
|
+
await expect(afterUpdate.handler(payload)).resolves.toBeUndefined();
|
|
65
|
+
expect(payload.data?._aiScore).toBeUndefined();
|
|
66
|
+
});
|
|
67
|
+
// The afterUpdate hook extracts each image's alt text, so an image WITH valid
|
|
68
|
+
// alt is not penalized as missing-alt and scores higher on accessibility than
|
|
69
|
+
// one without. (Regressions here mean the img/alt parsing broke again.)
|
|
70
|
+
it('scores an image WITH alt higher on accessibility than one WITHOUT alt', async () => {
|
|
71
|
+
const text = '<h2>Intro</h2><p>Simple readable sentences about coffee.</p>';
|
|
72
|
+
const withAlt = docPayload({
|
|
73
|
+
id: 'a',
|
|
74
|
+
data: {
|
|
75
|
+
title: 'A clear title',
|
|
76
|
+
metaDescription: 'A'.repeat(130),
|
|
77
|
+
body: `${text}<img src="a.jpg" alt="a dripper">`,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
const withoutAlt = docPayload({
|
|
81
|
+
id: 'b',
|
|
82
|
+
data: {
|
|
83
|
+
title: 'A clear title',
|
|
84
|
+
metaDescription: 'A'.repeat(130),
|
|
85
|
+
body: `${text}<img src="b.jpg">`,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
await afterUpdate.handler(withAlt);
|
|
89
|
+
await afterUpdate.handler(withoutAlt);
|
|
90
|
+
const a = withAlt.data._aiScore;
|
|
91
|
+
const b = withoutAlt.data._aiScore;
|
|
92
|
+
expect(b.breakdown.accessibility.score).toBeLessThan(a.breakdown.accessibility.score);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('aiHooks afterCreate — embedding generation', () => {
|
|
96
|
+
it('registers for the base afterCreate event', () => {
|
|
97
|
+
expect(afterCreate.event).toBe('afterCreate');
|
|
98
|
+
});
|
|
99
|
+
it('generates an embedding and attaches the provider vector as data._embedding', async () => {
|
|
100
|
+
setAIProvider(makeProvider(async () => [0.1, 0.2, 0.3]));
|
|
101
|
+
const payload = docPayload({ data: { body: 'Some article body' } });
|
|
102
|
+
await afterCreate.handler(payload);
|
|
103
|
+
expect(payload.data._embedding).toEqual([0.1, 0.2, 0.3]);
|
|
104
|
+
});
|
|
105
|
+
it('truncates the body to the first 8000 chars before embedding', async () => {
|
|
106
|
+
let received;
|
|
107
|
+
setAIProvider(makeProvider(async (text) => {
|
|
108
|
+
received = text;
|
|
109
|
+
return [1];
|
|
110
|
+
}));
|
|
111
|
+
await afterCreate.handler(docPayload({ data: { body: 'a'.repeat(10000) } }));
|
|
112
|
+
expect(received).toBeDefined();
|
|
113
|
+
expect(received.length).toBe(8000);
|
|
114
|
+
});
|
|
115
|
+
it('swallows provider errors — never rejects and never sets _embedding', async () => {
|
|
116
|
+
setAIProvider(makeProvider(async () => {
|
|
117
|
+
throw new Error('provider exploded');
|
|
118
|
+
}));
|
|
119
|
+
const payload = docPayload({ data: { body: 'x' } });
|
|
120
|
+
await expect(afterCreate.handler(payload)).resolves.toBeUndefined();
|
|
121
|
+
expect(payload.data._embedding).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=hooks.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.test.js","sourceRoot":"","sources":["../../src/__tests__/hooks.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plugin-config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
/**
|
|
3
|
+
* The real provider factories make no network call at construction, but they
|
|
4
|
+
* return opaque closures that don't expose the config they were built from. To
|
|
5
|
+
* assert that aiPlugin plumbs provider/apiKey/model/openaiApiKey through
|
|
6
|
+
* createAIProvider, we mock the two backend factories and inspect their args.
|
|
7
|
+
* createAIProvider + setAIProvider + getAIProvider (providers/index.ts) stay
|
|
8
|
+
* REAL, so the global-provider side effect is exercised end-to-end.
|
|
9
|
+
*/
|
|
10
|
+
const mocks = vi.hoisted(() => {
|
|
11
|
+
const fakeProvider = {
|
|
12
|
+
async generateText() {
|
|
13
|
+
return { text: '', usage: { promptTokens: 0, completionTokens: 0 } };
|
|
14
|
+
},
|
|
15
|
+
async generateEmbedding() {
|
|
16
|
+
return [0.42, 0.7, 0.13];
|
|
17
|
+
},
|
|
18
|
+
async *streamText() {
|
|
19
|
+
yield '';
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
fakeProvider,
|
|
24
|
+
createAnthropicProvider: vi.fn(() => fakeProvider),
|
|
25
|
+
createOpenAIProvider: vi.fn(() => fakeProvider),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
vi.mock('../providers/anthropic.js', () => ({
|
|
29
|
+
createAnthropicProvider: mocks.createAnthropicProvider,
|
|
30
|
+
}));
|
|
31
|
+
vi.mock('../providers/openai.js', () => ({
|
|
32
|
+
createOpenAIProvider: mocks.createOpenAIProvider,
|
|
33
|
+
}));
|
|
34
|
+
import { aiPlugin, getAIProvider } from '../index.js';
|
|
35
|
+
import { aiHooks } from '../hooks.js';
|
|
36
|
+
function docPayload(overrides = {}) {
|
|
37
|
+
return {
|
|
38
|
+
id: 'doc_1',
|
|
39
|
+
collection: 'articles',
|
|
40
|
+
slug: 'my-article',
|
|
41
|
+
status: 'published',
|
|
42
|
+
data: {},
|
|
43
|
+
...overrides,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// clearAllMocks resets call records but keeps the vi.fn(() => fakeProvider)
|
|
47
|
+
// implementation. It does NOT reset the real global-provider singleton, so the
|
|
48
|
+
// "no provider yet" assertions must (and do) run first.
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
vi.clearAllMocks();
|
|
51
|
+
});
|
|
52
|
+
describe('aiPlugin — provider wiring', () => {
|
|
53
|
+
it('has no global provider before any configuration', () => {
|
|
54
|
+
expect(getAIProvider()).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
it('does NOT wire a provider when apiKey is omitted', () => {
|
|
57
|
+
aiPlugin({ provider: 'openai' });
|
|
58
|
+
expect(mocks.createOpenAIProvider).not.toHaveBeenCalled();
|
|
59
|
+
expect(mocks.createAnthropicProvider).not.toHaveBeenCalled();
|
|
60
|
+
expect(getAIProvider()).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
it('wires the global provider when both provider and apiKey are supplied', () => {
|
|
63
|
+
aiPlugin({ provider: 'openai', apiKey: 'sk-test' });
|
|
64
|
+
expect(mocks.createOpenAIProvider).toHaveBeenCalledWith(expect.objectContaining({ apiKey: 'sk-test' }));
|
|
65
|
+
expect(getAIProvider()).toBe(mocks.fakeProvider);
|
|
66
|
+
});
|
|
67
|
+
it('forwards model and openaiApiKey through to the anthropic provider factory', () => {
|
|
68
|
+
aiPlugin({ provider: 'anthropic', apiKey: 'x', model: 'claude-y', openaiApiKey: 'sk' });
|
|
69
|
+
expect(mocks.createAnthropicProvider).toHaveBeenCalledWith({
|
|
70
|
+
apiKey: 'x',
|
|
71
|
+
model: 'claude-y',
|
|
72
|
+
openaiApiKey: 'sk',
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
it('the wired provider is actually used by the afterCreate hook to populate _embedding', async () => {
|
|
76
|
+
aiPlugin({ provider: 'openai', apiKey: 'sk-test' });
|
|
77
|
+
expect(getAIProvider()).toBe(mocks.fakeProvider);
|
|
78
|
+
const payload = docPayload({ data: { body: 'Some article body' } });
|
|
79
|
+
await aiHooks[1].handler(payload);
|
|
80
|
+
expect(payload.data._embedding).toEqual([0.42, 0.7, 0.13]);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('aiPlugin — feature flags are inert', () => {
|
|
84
|
+
// The scoring/brand/writing/translation/search .enabled flags are declared on
|
|
85
|
+
// AIPluginConfig but never read by aiPlugin: they gate nothing. This
|
|
86
|
+
// characterization test documents that scoring:{enabled:false} does NOT disable
|
|
87
|
+
// the afterUpdate scoring hook.
|
|
88
|
+
it('scoring:{enabled:false} still returns the scoring hooks and still computes _aiScore', async () => {
|
|
89
|
+
const plugin = aiPlugin({ scoring: { enabled: false } });
|
|
90
|
+
// Flags do not filter the hook set — the same aiHooks array is returned.
|
|
91
|
+
expect(plugin.hooks).toBe(aiHooks);
|
|
92
|
+
const payload = docPayload({
|
|
93
|
+
data: {
|
|
94
|
+
title: 'A clear title',
|
|
95
|
+
metaDescription: 'A'.repeat(130),
|
|
96
|
+
body: '<h2>Intro</h2><p>Simple readable sentences about coffee.</p>',
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
await aiHooks[0].handler(payload);
|
|
100
|
+
// Despite scoring being "disabled", the score is still attached.
|
|
101
|
+
expect(payload.data._aiScore).toBeDefined();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=plugin-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-config.test.js","sourceRoot":"","sources":["../../src/__tests__/plugin-config.test.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD,eAAO,MAAM,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD,eAAO,MAAM,OAAO,EAAE,UAAU,EAoF/B,CAAA"}
|
package/dist/hooks.js
CHANGED
|
@@ -20,11 +20,18 @@ export const aiHooks = [
|
|
|
20
20
|
metaDescription: doc.data?.metaDescription ?? '',
|
|
21
21
|
body,
|
|
22
22
|
});
|
|
23
|
-
|
|
23
|
+
// Match each <img> tag, then pull `src`/`alt` out separately. A single
|
|
24
|
+
// combined regex fails here: a greedy `[^>]*` before an optional
|
|
25
|
+
// `alt="…"` group consumes the whole tag, so `alt` is never captured and
|
|
26
|
+
// every image looks like it's missing alt text regardless of order.
|
|
27
|
+
const imgTagRegex = /<img\s[^>]*>/gi;
|
|
24
28
|
const images = [];
|
|
25
29
|
let imgMatch;
|
|
26
|
-
while ((imgMatch =
|
|
27
|
-
|
|
30
|
+
while ((imgMatch = imgTagRegex.exec(body)) !== null) {
|
|
31
|
+
const tag = imgMatch[0];
|
|
32
|
+
const src = /\ssrc="([^"]*)"/i.exec(tag)?.[1] ?? '';
|
|
33
|
+
const altAttr = /\salt="([^"]*)"/i.exec(tag);
|
|
34
|
+
images.push({ src, alt: altAttr ? altAttr[1] : undefined });
|
|
28
35
|
}
|
|
29
36
|
const linkRegex = /<a\s[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>/gi;
|
|
30
37
|
const links = [];
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG1D,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC;QACE,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,KAAK,EAAE,QAAiB,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,QAKX,CAAA;YAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAK,GAAG,CAAC,IAAI,EAAE,IAAe,IAAI,EAAE,CAAA;YACzD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAK,GAAG,CAAC,IAAI,EAAE,KAAgB,IAAI,EAAE,CAAA;YAC5D,IAAI,CAAC,IAAI;gBAAE,OAAM;YAEjB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;gBAC7C,MAAM,GAAG,GAAG,iBAAiB,CAAC;oBAC5B,KAAK;oBACL,eAAe,EAAG,GAAG,CAAC,IAAI,EAAE,eAA0B,IAAI,EAAE;oBAC5D,IAAI;iBACL,CAAC,CAAA;gBACF,MAAM,
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG1D,MAAM,CAAC,MAAM,OAAO,GAAiB;IACnC;QACE,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,KAAK,EAAE,QAAiB,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,QAKX,CAAA;YAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAK,GAAG,CAAC,IAAI,EAAE,IAAe,IAAI,EAAE,CAAA;YACzD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAK,GAAG,CAAC,IAAI,EAAE,KAAgB,IAAI,EAAE,CAAA;YAC5D,IAAI,CAAC,IAAI;gBAAE,OAAM;YAEjB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAA;gBAC7C,MAAM,GAAG,GAAG,iBAAiB,CAAC;oBAC5B,KAAK;oBACL,eAAe,EAAG,GAAG,CAAC,IAAI,EAAE,eAA0B,IAAI,EAAE;oBAC5D,IAAI;iBACL,CAAC,CAAA;gBACF,uEAAuE;gBACvE,iEAAiE;gBACjE,yEAAyE;gBACzE,oEAAoE;gBACpE,MAAM,WAAW,GAAG,gBAAgB,CAAA;gBACpC,MAAM,MAAM,GAAyC,EAAE,CAAA;gBACvD,IAAI,QAAgC,CAAA;gBACpC,OAAO,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;oBACvB,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;oBACnD,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;oBAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;gBAC7D,CAAC;gBAED,MAAM,SAAS,GAAG,6CAA6C,CAAA;gBAC/D,MAAM,KAAK,GAA0C,EAAE,CAAA;gBACvD,IAAI,SAAiC,CAAA;gBACrC,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;gBACpE,CAAC;gBAED,MAAM,YAAY,GAAG,qBAAqB,CAAA;gBAC1C,MAAM,QAAQ,GAAa,EAAE,CAAA;gBAC7B,IAAI,MAA8B,CAAA;gBAClC,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBACnD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;gBAChC,CAAC;gBAED,MAAM,IAAI,GAAG,2BAA2B,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;gBAEjF,MAAM,KAAK,GAAG,uBAAuB,CAAC;oBACpC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,WAAW,CAAC,iBAAiB,GAAG,CAAC,CAAC;oBACjE,GAAG,EAAE,GAAG,CAAC,KAAK;oBACd,aAAa,EAAE,IAAI,CAAC,KAAK;iBAC1B,CAAC,CAAA;gBAEF,oDAAoD;gBACpD,IAAI,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC7C,CAAC;oBAAC,GAAG,CAAC,IAAY,CAAC,QAAQ,GAAG,KAAK,CAAA;gBACrC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;KACF;IACD;QACE,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,KAAK,EAAE,QAAiB,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,QAAyE,CAAA;YACrF,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAK,GAAG,CAAC,IAAI,EAAE,IAAe,IAAI,EAAE,CAAA;YACzD,IAAI,CAAC,IAAI;gBAAE,OAAM;YAEjB,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAA;YAChC,IAAI,CAAC,QAAQ;gBAAE,OAAM;YAErB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAA;gBAExE,IAAI,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC7C,CAAC;oBAAC,GAAG,CAAC,IAAY,CAAC,UAAU,GAAG,SAAS,CAAC,MAAM,CAAA;gBAClD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;KACF;CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actuate-media/plugin-ai",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"@types/react": "^19.0.0",
|
|
29
29
|
"typescript": "^5.7.0",
|
|
30
30
|
"vitest": "^4.1.0",
|
|
31
|
-
"@actuate-media/cms-core": "0.
|
|
31
|
+
"@actuate-media/cms-core": "0.95.1"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@actuate-media/cms-core": ">=0.1.0",
|
|
35
|
-
"react": "^19.
|
|
35
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "tsc --project tsconfig.json",
|