@mayson-org/inject-script 1.0.0 → 1.0.3
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/.env.example +9 -0
- package/README.md +57 -45
- package/bin/cli.mjs +1 -158
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/core/find-root-layout.d.ts +2 -0
- package/dist/core/find-root-layout.d.ts.map +1 -0
- package/dist/core/find-root-layout.js +61 -0
- package/dist/core/generators.d.ts +4 -0
- package/dist/core/generators.d.ts.map +1 -0
- package/dist/core/generators.js +37 -0
- package/dist/core/injector.d.ts +4 -0
- package/dist/core/injector.d.ts.map +1 -0
- package/dist/core/injector.js +76 -0
- package/dist/core/types.d.ts +48 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/find-root-layout.d.ts +0 -3
- package/dist/find-root-layout.d.ts.map +1 -1
- package/dist/find-root-layout.js +1 -15
- package/dist/generators.d.ts +13 -0
- package/dist/generators.d.ts.map +1 -0
- package/dist/generators.js +134 -0
- package/dist/index.d.ts +14 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -9
- package/dist/injector.d.ts +5 -3
- package/dist/injector.d.ts.map +1 -1
- package/dist/injector.js +67 -61
- package/dist/plugins/ascii/index.d.ts +3 -0
- package/dist/plugins/ascii/index.d.ts.map +1 -0
- package/dist/plugins/ascii/index.js +25 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/metadata/index.d.ts +3 -0
- package/dist/plugins/metadata/index.d.ts.map +1 -0
- package/dist/plugins/metadata/index.js +14 -0
- package/dist/plugins/watermark/index.d.ts +4 -0
- package/dist/plugins/watermark/index.d.ts.map +1 -0
- package/dist/plugins/watermark/index.js +7 -0
- package/dist/plugins/watermark/template.d.ts +9 -0
- package/dist/plugins/watermark/template.d.ts.map +1 -0
- package/dist/plugins/watermark/template.js +128 -0
- package/dist/shared/config.d.ts +13 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +25 -0
- package/dist/shared/generated-app-metadata.d.ts +28 -0
- package/dist/shared/generated-app-metadata.d.ts.map +1 -0
- package/dist/shared/generated-app-metadata.js +103 -0
- package/dist/shared/remix-url.d.ts +13 -0
- package/dist/shared/remix-url.d.ts.map +1 -0
- package/dist/shared/remix-url.js +16 -0
- package/package.json +15 -8
- package/src/find-root-layout.ts +0 -88
- package/src/index.ts +0 -27
- package/src/injector.ts +0 -101
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-root-layout.d.ts","sourceRoot":"","sources":["../src/find-root-layout.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"find-root-layout.d.ts","sourceRoot":"","sources":["../src/find-root-layout.ts"],"names":[],"mappings":"AAgDA,wBAAgB,cAAc,CAAC,WAAW,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CA0BjF"}
|
package/dist/find-root-layout.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
const LAYOUT_EXTENSIONS = ['.tsx', '.jsx', '.ts', '.js'];
|
|
4
|
-
/**
|
|
5
|
-
* Recursively search a directory for layout files.
|
|
6
|
-
*/
|
|
7
4
|
function findLayoutFiles(dir, fileList = []) {
|
|
8
5
|
if (!fs.existsSync(dir))
|
|
9
6
|
return fileList;
|
|
@@ -11,7 +8,6 @@ function findLayoutFiles(dir, fileList = []) {
|
|
|
11
8
|
for (const entry of entries) {
|
|
12
9
|
const fullPath = path.join(dir, entry.name);
|
|
13
10
|
if (entry.isDirectory()) {
|
|
14
|
-
// Don't traverse node_modules or hidden folders (.next, .git)
|
|
15
11
|
if (entry.name === 'node_modules' || entry.name.startsWith('.')) {
|
|
16
12
|
continue;
|
|
17
13
|
}
|
|
@@ -27,30 +23,21 @@ function findLayoutFiles(dir, fileList = []) {
|
|
|
27
23
|
}
|
|
28
24
|
return fileList;
|
|
29
25
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Scores a layout file candidate to determine if it is the root layout.
|
|
32
|
-
* Higher score = higher likelihood of being the root layout.
|
|
33
|
-
*/
|
|
34
26
|
function scoreLayoutCandidate(filePath, projectRoot) {
|
|
35
27
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
36
28
|
const relativePath = path.relative(projectRoot, filePath);
|
|
37
29
|
const depth = relativePath.split(path.sep).length;
|
|
38
|
-
let score = 100 - depth;
|
|
39
|
-
// Check for HTML/Body root tags
|
|
30
|
+
let score = 100 - depth;
|
|
40
31
|
if (/<html/i.test(content))
|
|
41
32
|
score += 50;
|
|
42
33
|
if (/<body/i.test(content))
|
|
43
34
|
score += 50;
|
|
44
|
-
// Check if located directly under app/ or src/app/
|
|
45
35
|
const isDirectAppChild = /^src[/\\]app[/\\]layout\.[jt]sx?$/.test(relativePath) ||
|
|
46
36
|
/^app[/\\]layout\.[jt]sx?$/.test(relativePath);
|
|
47
37
|
if (isDirectAppChild)
|
|
48
38
|
score += 40;
|
|
49
39
|
return score;
|
|
50
40
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Finds the most likely Next.js App Router root layout file in a project.
|
|
53
|
-
*/
|
|
54
41
|
export function findRootLayout(projectRoot = process.cwd()) {
|
|
55
42
|
const possibleAppDirs = [
|
|
56
43
|
path.join(projectRoot, 'src', 'app'),
|
|
@@ -65,7 +52,6 @@ export function findRootLayout(projectRoot = process.cwd()) {
|
|
|
65
52
|
if (candidateFiles.length === 0) {
|
|
66
53
|
return null;
|
|
67
54
|
}
|
|
68
|
-
// Score each candidate to pick the true root layout
|
|
69
55
|
const scored = candidateFiles.map((filePath) => ({
|
|
70
56
|
filePath,
|
|
71
57
|
score: scoreLayoutCandidate(filePath, projectRoot),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ComponentType = 'badge' | 'watermark' | 'ascii' | 'metadata' | 'all';
|
|
2
|
+
export interface ComponentGeneratorOptions {
|
|
3
|
+
outputDir: string;
|
|
4
|
+
isTypeScript?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface GeneratedComponentInfo {
|
|
7
|
+
name: string;
|
|
8
|
+
filePath: string;
|
|
9
|
+
importStatement: string;
|
|
10
|
+
jsxTag: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function generateComponents(types: ComponentType[] | undefined, options: ComponentGeneratorOptions): GeneratedComponentInfo[];
|
|
13
|
+
//# sourceMappingURL=generators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AA8FD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EAAE,YAAY,EAClC,OAAO,EAAE,yBAAyB,GACjC,sBAAsB,EAAE,CAkD1B"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const BADGE_TEMPLATE = `'use client';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
export function MaysonBadge() {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
style={{
|
|
10
|
+
position: 'fixed',
|
|
11
|
+
bottom: '16px',
|
|
12
|
+
right: '16px',
|
|
13
|
+
zIndex: 99999,
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
gap: '8px',
|
|
17
|
+
padding: '6px 12px',
|
|
18
|
+
backgroundColor: 'rgba(18, 18, 20, 0.9)',
|
|
19
|
+
color: '#ffffff',
|
|
20
|
+
borderRadius: '9999px',
|
|
21
|
+
fontSize: '12px',
|
|
22
|
+
fontWeight: 500,
|
|
23
|
+
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
24
|
+
border: '1px solid rgba(255, 255, 255, 0.15)',
|
|
25
|
+
boxShadow: '0 4px 14px rgba(0, 0, 0, 0.25)',
|
|
26
|
+
backdropFilter: 'blur(8px)',
|
|
27
|
+
cursor: 'pointer',
|
|
28
|
+
userSelect: 'none',
|
|
29
|
+
transition: 'transform 0.2s ease',
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<span style={{ width: '8px', height: '8px', borderRadius: '50%', backgroundColor: '#6366f1' }} />
|
|
33
|
+
<span>Built with <strong>Mayson</strong></span>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
const WATERMARK_TEMPLATE = `'use client';
|
|
39
|
+
import React from 'react';
|
|
40
|
+
|
|
41
|
+
export function MaysonWatermark() {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
style={{
|
|
45
|
+
position: 'fixed',
|
|
46
|
+
bottom: '12px',
|
|
47
|
+
left: '12px',
|
|
48
|
+
zIndex: 99999,
|
|
49
|
+
opacity: 0.4,
|
|
50
|
+
fontSize: '11px',
|
|
51
|
+
fontFamily: 'monospace',
|
|
52
|
+
color: '#888888',
|
|
53
|
+
pointerEvents: 'none',
|
|
54
|
+
userSelect: 'none',
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
⚡ Mayson Watermark
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
const ASCII_TEMPLATE = `'use client';
|
|
63
|
+
import React, { useEffect } from 'react';
|
|
64
|
+
|
|
65
|
+
const ASCII_ART = \`
|
|
66
|
+
███╗ ███╗█████╗ ██╗ ██╗███████╗██████╗ ██████╗
|
|
67
|
+
████╗ ████║██╔══██╗╚██╗ ██╔╝██╔════╝██╔═══██╗██╔══██╗
|
|
68
|
+
██╔████╔██║███████║ ╚████╔╝ ███████╗██║ ██║██║ ██║
|
|
69
|
+
██║╚██╔╝██║██╔══██║ ╚██╔╝ ╚════██║██║ ██║██║ ██║
|
|
70
|
+
██║ ╚═╝ ██║██║ ██║ ██║ ███████║╚██████╔╝██████╔╝
|
|
71
|
+
\`;
|
|
72
|
+
|
|
73
|
+
export function MaysonAscii() {
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
console.log('%c' + ASCII_ART, 'color: #6366f1; font-weight: bold;');
|
|
76
|
+
console.log('%c🚀 Powered by Mayson Platform', 'color: #10b981; font-weight: bold; font-size: 12px;');
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
const METADATA_TEMPLATE = `'use client';
|
|
83
|
+
import React from 'react';
|
|
84
|
+
|
|
85
|
+
export function MaysonMetadata() {
|
|
86
|
+
return (
|
|
87
|
+
<meta name="mayson-generator" content="Mayson App Platform" />
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
export function generateComponents(types = ['badge'], options) {
|
|
92
|
+
const { outputDir, isTypeScript = true } = options;
|
|
93
|
+
const ext = isTypeScript ? '.tsx' : '.jsx';
|
|
94
|
+
const results = [];
|
|
95
|
+
if (!fs.existsSync(outputDir)) {
|
|
96
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
const selectedTypes = types.includes('all')
|
|
99
|
+
? ['badge', 'watermark', 'ascii', 'metadata']
|
|
100
|
+
: types;
|
|
101
|
+
for (const type of selectedTypes) {
|
|
102
|
+
let name = '';
|
|
103
|
+
let code = '';
|
|
104
|
+
switch (type) {
|
|
105
|
+
case 'badge':
|
|
106
|
+
name = 'MaysonBadge';
|
|
107
|
+
code = BADGE_TEMPLATE;
|
|
108
|
+
break;
|
|
109
|
+
case 'watermark':
|
|
110
|
+
name = 'MaysonWatermark';
|
|
111
|
+
code = WATERMARK_TEMPLATE;
|
|
112
|
+
break;
|
|
113
|
+
case 'ascii':
|
|
114
|
+
name = 'MaysonAscii';
|
|
115
|
+
code = ASCII_TEMPLATE;
|
|
116
|
+
break;
|
|
117
|
+
case 'metadata':
|
|
118
|
+
name = 'MaysonMetadata';
|
|
119
|
+
code = METADATA_TEMPLATE;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (name && code) {
|
|
123
|
+
const filePath = path.join(outputDir, `${name}${ext}`);
|
|
124
|
+
fs.writeFileSync(filePath, code, 'utf-8');
|
|
125
|
+
results.push({
|
|
126
|
+
name,
|
|
127
|
+
filePath,
|
|
128
|
+
importStatement: `import { ${name} } from './${name}';`,
|
|
129
|
+
jsxTag: `<${name} />`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return results;
|
|
134
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
1
|
+
import type { ComponentType, InjectorResult } from './core/types.js';
|
|
2
|
+
export { findRootLayout } from './core/find-root-layout.js';
|
|
3
|
+
export { generateComponents } from './core/generators.js';
|
|
4
|
+
export { injectComponentsIntoLayout } from './core/injector.js';
|
|
5
|
+
export { buildRemixRedirectUrl, BADGE_UTM_SOURCE } from './shared/remix-url.js';
|
|
6
|
+
export type { RemixUrlConfig } from './shared/remix-url.js';
|
|
7
|
+
export { loadMaysonEnvConfig } from './shared/config.js';
|
|
8
|
+
export type { MaysonEnvConfig } from './shared/config.js';
|
|
9
|
+
export { fetchGeneratedAppMetadata, resolveMaysonConfig, shouldFetchGeneratedAppMetadata, } from './shared/generated-app-metadata.js';
|
|
10
|
+
export { watermarkPlugin, buildMaysonWatermarkSource, } from './plugins/watermark/index.js';
|
|
11
|
+
export type { ComponentType, GeneratedComponentInfo, ComponentGeneratorOptions, InjectorOptions, InjectorResult, MaysonPlugin, PluginGenerateContext, } from './core/types.js';
|
|
5
12
|
/**
|
|
6
|
-
*
|
|
13
|
+
* Auto-detect root layout, fetch watermark flags from generated-app-metadata when
|
|
14
|
+
* configured, generate component files, and inject them.
|
|
7
15
|
*/
|
|
8
|
-
export declare function runAutoInject(projectRoot?: string,
|
|
16
|
+
export declare function runAutoInject(projectRoot?: string, types?: ComponentType[], dryRun?: boolean): Promise<InjectorResult>;
|
|
9
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAEf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChF,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAwBzB;;;GAGG;AACH,wBAAsB,aAAa,CACjC,WAAW,GAAE,MAAsB,EACnC,KAAK,GAAE,aAAa,EAAkB,EACtC,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,78 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { findRootLayout } from './core/find-root-layout.js';
|
|
3
|
+
import { generateComponents } from './core/generators.js';
|
|
4
|
+
import { injectComponentsIntoLayout } from './core/injector.js';
|
|
5
|
+
import { resolveMaysonConfig } from './shared/generated-app-metadata.js';
|
|
6
|
+
export { findRootLayout } from './core/find-root-layout.js';
|
|
7
|
+
export { generateComponents } from './core/generators.js';
|
|
8
|
+
export { injectComponentsIntoLayout } from './core/injector.js';
|
|
9
|
+
export { buildRemixRedirectUrl, BADGE_UTM_SOURCE } from './shared/remix-url.js';
|
|
10
|
+
export { loadMaysonEnvConfig } from './shared/config.js';
|
|
11
|
+
export { fetchGeneratedAppMetadata, resolveMaysonConfig, shouldFetchGeneratedAppMetadata, } from './shared/generated-app-metadata.js';
|
|
12
|
+
export { watermarkPlugin, buildMaysonWatermarkSource, } from './plugins/watermark/index.js';
|
|
13
|
+
function filterTypesForConfig(types, showRemixPill) {
|
|
14
|
+
const messages = [];
|
|
15
|
+
const selected = types.includes('all')
|
|
16
|
+
? ['watermark', 'ascii', 'metadata']
|
|
17
|
+
: types;
|
|
18
|
+
if (selected.includes('watermark') && !showRemixPill) {
|
|
19
|
+
messages.push('watermark skipped — show_remix_pill is false (set via generated-app-metadata API)');
|
|
20
|
+
return {
|
|
21
|
+
types: selected.filter((t) => t !== 'watermark'),
|
|
22
|
+
messages,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { types: selected, messages };
|
|
26
|
+
}
|
|
4
27
|
/**
|
|
5
|
-
*
|
|
28
|
+
* Auto-detect root layout, fetch watermark flags from generated-app-metadata when
|
|
29
|
+
* configured, generate component files, and inject them.
|
|
6
30
|
*/
|
|
7
|
-
export function runAutoInject(projectRoot = process.cwd(),
|
|
31
|
+
export async function runAutoInject(projectRoot = process.cwd(), types = ['watermark'], dryRun = false) {
|
|
8
32
|
const layoutPath = findRootLayout(projectRoot);
|
|
9
33
|
if (!layoutPath) {
|
|
10
34
|
return {
|
|
11
35
|
success: false,
|
|
12
36
|
filePath: '',
|
|
13
|
-
|
|
14
|
-
|
|
37
|
+
injectedComponents: [],
|
|
38
|
+
skippedComponents: [],
|
|
39
|
+
error: `Could not locate Next.js App Router root layout in ${projectRoot}`,
|
|
15
40
|
};
|
|
16
41
|
}
|
|
17
|
-
|
|
42
|
+
const config = await resolveMaysonConfig();
|
|
43
|
+
const { types: effectiveTypes, messages } = filterTypesForConfig(types, config.showRemixPill);
|
|
44
|
+
if (effectiveTypes.length === 0) {
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
filePath: layoutPath,
|
|
48
|
+
injectedComponents: [],
|
|
49
|
+
skippedComponents: [],
|
|
50
|
+
messages,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const context = {
|
|
54
|
+
watermark: {
|
|
55
|
+
showRemixPill: config.showRemixPill,
|
|
56
|
+
enableRemix: config.enableRemix,
|
|
57
|
+
appBaseUrl: config.appBaseUrl,
|
|
58
|
+
collectionId: config.collectionId,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const isTypeScript = layoutPath.endsWith('.tsx') || layoutPath.endsWith('.ts');
|
|
62
|
+
const targetDir = path.dirname(layoutPath);
|
|
63
|
+
const generatedComponents = generateComponents(effectiveTypes, {
|
|
64
|
+
outputDir: targetDir,
|
|
65
|
+
isTypeScript,
|
|
66
|
+
dryRun,
|
|
67
|
+
context,
|
|
68
|
+
});
|
|
69
|
+
const result = injectComponentsIntoLayout({
|
|
18
70
|
filePath: layoutPath,
|
|
19
|
-
|
|
71
|
+
components: generatedComponents,
|
|
20
72
|
dryRun,
|
|
21
73
|
});
|
|
74
|
+
return {
|
|
75
|
+
...result,
|
|
76
|
+
messages: [...(result.messages ?? []), ...messages],
|
|
77
|
+
};
|
|
22
78
|
}
|
package/dist/injector.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { GeneratedComponentInfo } from './generators.js';
|
|
1
2
|
export interface InjectorOptions {
|
|
2
3
|
filePath: string;
|
|
3
|
-
|
|
4
|
+
components: GeneratedComponentInfo[];
|
|
4
5
|
dryRun?: boolean;
|
|
5
6
|
}
|
|
6
7
|
export interface InjectorResult {
|
|
7
8
|
success: boolean;
|
|
8
9
|
filePath: string;
|
|
9
|
-
|
|
10
|
+
injectedComponents: string[];
|
|
11
|
+
skippedComponents: string[];
|
|
10
12
|
modifiedContent?: string;
|
|
11
13
|
error?: string;
|
|
12
14
|
}
|
|
13
|
-
export declare function
|
|
15
|
+
export declare function injectComponentsIntoLayout(options: InjectorOptions): InjectorResult;
|
|
14
16
|
//# sourceMappingURL=injector.d.ts.map
|
package/dist/injector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../src/injector.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../src/injector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAwFnF"}
|
package/dist/injector.js
CHANGED
|
@@ -1,76 +1,82 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
|
|
3
|
-
export function
|
|
4
|
-
const { filePath,
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export function injectComponentsIntoLayout(options) {
|
|
4
|
+
const { filePath, components, dryRun = false } = options;
|
|
5
5
|
if (!fs.existsSync(filePath)) {
|
|
6
6
|
return {
|
|
7
7
|
success: false,
|
|
8
8
|
filePath,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
injectedComponents: [],
|
|
10
|
+
skippedComponents: [],
|
|
11
|
+
error: `Layout file not found: ${filePath}`,
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{${INJECTION_MARKER}}
|
|
24
|
-
<iframe
|
|
25
|
-
src="${iframeUrl}"
|
|
26
|
-
style={{
|
|
27
|
-
position: 'fixed',
|
|
28
|
-
bottom: '20px',
|
|
29
|
-
right: '20px',
|
|
30
|
-
width: '400px',
|
|
31
|
-
height: '600px',
|
|
32
|
-
border: 'none',
|
|
33
|
-
borderRadius: '12px',
|
|
34
|
-
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.25)',
|
|
35
|
-
zIndex: 999999,
|
|
36
|
-
}}
|
|
37
|
-
title="Mayson Dev Overlay"
|
|
38
|
-
/>`;
|
|
39
|
-
let updatedContent = null;
|
|
40
|
-
// Option 1: Inject before </body>
|
|
41
|
-
if (/<\/body>/i.test(content)) {
|
|
42
|
-
updatedContent = content.replace(/<\/body>/i, `${snippet}\n </body>`);
|
|
43
|
-
}
|
|
44
|
-
// Option 2: Inject before </html>
|
|
45
|
-
else if (/<\/html>/i.test(content)) {
|
|
46
|
-
updatedContent = content.replace(/<\/html>/i, `${snippet}\n </html>`);
|
|
47
|
-
}
|
|
48
|
-
// Option 3: Inject before the closing tag of the return block (e.g. </main> or </div>)
|
|
49
|
-
else {
|
|
50
|
-
const lastClosingTagIndex = content.lastIndexOf('</');
|
|
51
|
-
if (lastClosingTagIndex !== -1) {
|
|
52
|
-
updatedContent =
|
|
53
|
-
content.slice(0, lastClosingTagIndex) +
|
|
54
|
-
snippet +
|
|
55
|
-
'\n ' +
|
|
56
|
-
content.slice(lastClosingTagIndex);
|
|
14
|
+
let content = fs.readFileSync(filePath, 'utf-8');
|
|
15
|
+
const injectedComponents = [];
|
|
16
|
+
const skippedComponents = [];
|
|
17
|
+
for (const comp of components) {
|
|
18
|
+
const importMarker = comp.name;
|
|
19
|
+
const jsxMarker = `<${comp.name}`;
|
|
20
|
+
// Skip if already injected
|
|
21
|
+
if (content.includes(importMarker) || content.includes(jsxMarker)) {
|
|
22
|
+
skippedComponents.push(comp.name);
|
|
23
|
+
continue;
|
|
57
24
|
}
|
|
25
|
+
// Determine component file import path relative to layout.tsx
|
|
26
|
+
const layoutDir = path.dirname(filePath);
|
|
27
|
+
const compDir = path.dirname(comp.filePath);
|
|
28
|
+
const compBaseName = path.basename(comp.filePath, path.extname(comp.filePath));
|
|
29
|
+
let relativeImportPath = path.relative(layoutDir, path.join(compDir, compBaseName));
|
|
30
|
+
if (!relativeImportPath.startsWith('.')) {
|
|
31
|
+
relativeImportPath = `./${relativeImportPath}`;
|
|
32
|
+
}
|
|
33
|
+
// Convert backslashes for Windows path consistency
|
|
34
|
+
relativeImportPath = relativeImportPath.replace(/\\/g, '/');
|
|
35
|
+
const importLine = `import { ${comp.name} } from '${relativeImportPath}';\n`;
|
|
36
|
+
// 1. Insert import statement
|
|
37
|
+
if (/import\s+.*?from\s+['"].*?['"];?/g.test(content)) {
|
|
38
|
+
// Insert after the last import statement
|
|
39
|
+
const importMatches = Array.from(content.matchAll(/import\s+.*?from\s+['"].*?['"];?/g));
|
|
40
|
+
const lastMatch = importMatches[importMatches.length - 1];
|
|
41
|
+
if (lastMatch && lastMatch.index !== undefined) {
|
|
42
|
+
const insertPos = lastMatch.index + lastMatch[0].length;
|
|
43
|
+
content = content.slice(0, insertPos) + '\n' + importLine + content.slice(insertPos);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
content = importLine + content;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
content = importLine + content;
|
|
51
|
+
}
|
|
52
|
+
// 2. Insert JSX tag into return block
|
|
53
|
+
const jsxSnippet = `\n {/* @mayson-component-injected: ${comp.name} */}\n ${comp.jsxTag}`;
|
|
54
|
+
if (/<\/body>/i.test(content)) {
|
|
55
|
+
content = content.replace(/<\/body>/i, `${jsxSnippet}\n </body>`);
|
|
56
|
+
}
|
|
57
|
+
else if (/<\/html>/i.test(content)) {
|
|
58
|
+
content = content.replace(/<\/html>/i, `${jsxSnippet}\n </html>`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const lastClosingIndex = content.lastIndexOf('</');
|
|
62
|
+
if (lastClosingIndex !== -1) {
|
|
63
|
+
content =
|
|
64
|
+
content.slice(0, lastClosingIndex) +
|
|
65
|
+
jsxSnippet +
|
|
66
|
+
'\n ' +
|
|
67
|
+
content.slice(lastClosingIndex);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
injectedComponents.push(comp.name);
|
|
58
71
|
}
|
|
59
|
-
if (!
|
|
60
|
-
|
|
61
|
-
success: false,
|
|
62
|
-
filePath,
|
|
63
|
-
alreadyInjected: false,
|
|
64
|
-
error: 'Could not find suitable JSX insertion point in layout file.',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (!dryRun) {
|
|
68
|
-
fs.writeFileSync(filePath, updatedContent, 'utf-8');
|
|
72
|
+
if (injectedComponents.length > 0 && !dryRun) {
|
|
73
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
69
74
|
}
|
|
70
75
|
return {
|
|
71
76
|
success: true,
|
|
72
77
|
filePath,
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
injectedComponents,
|
|
79
|
+
skippedComponents,
|
|
80
|
+
modifiedContent: content,
|
|
75
81
|
};
|
|
76
82
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/ascii/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAuBxD,eAAO,MAAM,WAAW,EAAE,YAIzB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const ASCII_SOURCE = `'use client';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
const ASCII_ART = \`
|
|
5
|
+
███╗ ███╗█████╗ ██╗ ██╗███████╗██████╗ ██████╗
|
|
6
|
+
████╗ ████║██╔══██╗╚██╗ ██╔╝██╔════╝██╔═══██╗██╔══██╗
|
|
7
|
+
██╔████╔██║███████║ ╚████╔╝ ███████╗██║ ██║██║ ██║
|
|
8
|
+
██║╚██╔╝██║██╔══██║ ╚██╔╝ ╚════██║██║ ██║██║ ██║
|
|
9
|
+
██║ ╚═╝ ██║██║ ██║ ██║ ███████║╚██████╔╝██████╔╝
|
|
10
|
+
\`;
|
|
11
|
+
|
|
12
|
+
export function MaysonAscii() {
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
console.log('%c' + ASCII_ART, 'color: #6366f1; font-weight: bold;');
|
|
15
|
+
console.log('%c🚀 Powered by Mayson Platform', 'color: #10b981; font-weight: bold; font-size: 12px;');
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
export const asciiPlugin = {
|
|
22
|
+
type: 'ascii',
|
|
23
|
+
name: 'MaysonAscii',
|
|
24
|
+
generateSource: () => ASCII_SOURCE,
|
|
25
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MaysonPlugin } from '../core/types.js';
|
|
2
|
+
import { asciiPlugin } from './ascii/index.js';
|
|
3
|
+
import { metadataPlugin } from './metadata/index.js';
|
|
4
|
+
import { watermarkPlugin } from './watermark/index.js';
|
|
5
|
+
export declare const plugins: Record<Exclude<MaysonPlugin['type'], never>, MaysonPlugin>;
|
|
6
|
+
export { watermarkPlugin, asciiPlugin, metadataPlugin };
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,YAAY,CAI9E,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { asciiPlugin } from './ascii/index.js';
|
|
2
|
+
import { metadataPlugin } from './metadata/index.js';
|
|
3
|
+
import { watermarkPlugin } from './watermark/index.js';
|
|
4
|
+
export const plugins = {
|
|
5
|
+
watermark: watermarkPlugin,
|
|
6
|
+
ascii: asciiPlugin,
|
|
7
|
+
metadata: metadataPlugin,
|
|
8
|
+
};
|
|
9
|
+
export { watermarkPlugin, asciiPlugin, metadataPlugin };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/metadata/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAYxD,eAAO,MAAM,cAAc,EAAE,YAI5B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const METADATA_SOURCE = `'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
export function MaysonMetadata() {
|
|
5
|
+
return (
|
|
6
|
+
<meta name="mayson-generator" content="Mayson App Platform" />
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
export const metadataPlugin = {
|
|
11
|
+
type: 'metadata',
|
|
12
|
+
name: 'MaysonMetadata',
|
|
13
|
+
generateSource: () => METADATA_SOURCE,
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/watermark/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,eAAe,EAAE,YAI7B,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { buildMaysonWatermarkSource } from './template.js';
|
|
2
|
+
export const watermarkPlugin = {
|
|
3
|
+
type: 'watermark',
|
|
4
|
+
name: 'MaysonWatermark',
|
|
5
|
+
generateSource: (context) => buildMaysonWatermarkSource(context),
|
|
6
|
+
};
|
|
7
|
+
export { buildMaysonWatermarkSource } from './template.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PluginGenerateContext } from '../../core/types.js';
|
|
2
|
+
export type WatermarkTemplateOptions = {
|
|
3
|
+
enableRemix: boolean;
|
|
4
|
+
appBaseUrl: string;
|
|
5
|
+
collectionId: string;
|
|
6
|
+
};
|
|
7
|
+
/** Source for the consumer-app MaysonWatermark client component. */
|
|
8
|
+
export declare function buildMaysonWatermarkSource(context?: PluginGenerateContext): string;
|
|
9
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/plugins/watermark/template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAIjE,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAaF,oEAAoE;AACpE,wBAAgB,0BAA0B,CACxC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,MAAM,CAqHR"}
|