@gemigo/extension-sdk 0.1.2 → 0.2.1

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 CHANGED
@@ -4,17 +4,12 @@ GemiGo Extension SDK for building apps that run inside the GemiGo browser extens
4
4
 
5
5
  ## Installation
6
6
 
7
- ### CDN (Recommended for simple apps)
7
+ ### CDN (Recommended)
8
8
 
9
9
  ```html
10
10
  <script src="https://unpkg.com/@gemigo/extension-sdk/dist/gemigo-extension-sdk.umd.js"></script>
11
11
  ```
12
12
 
13
- Or use jsDelivr:
14
- ```html
15
- <script src="https://cdn.jsdelivr.net/npm/@gemigo/extension-sdk/dist/gemigo-extension-sdk.umd.js"></script>
16
- ```
17
-
18
13
  ### npm
19
14
 
20
15
  ```bash
@@ -23,39 +18,22 @@ npm install @gemigo/extension-sdk
23
18
 
24
19
  ## Quick Start
25
20
 
26
- ### CDN Usage
27
-
28
21
  ```html
29
22
  <script src="https://unpkg.com/@gemigo/extension-sdk/dist/gemigo-extension-sdk.umd.js"></script>
30
23
  <script>
31
- GemigoExtensionSDK.connect().then((gemigo) => {
32
- // Get current page info
33
- gemigo.getPageInfo().then(console.log);
34
-
35
- // Subscribe to context menu events
36
- gemigo.on('contextMenu', (event) => {
37
- console.log('Menu clicked:', event.menuId, event.selectionText);
38
- });
24
+ // SDK auto-connects, use gemigo.extension.* APIs directly
25
+ gemigo.extension.getPageInfo().then(console.log);
26
+
27
+ // Subscribe to context menu events
28
+ gemigo.extension.onContextMenu((event) => {
29
+ console.log('Menu clicked:', event.menuId, event.selectionText);
39
30
  });
40
31
  </script>
41
32
  ```
42
33
 
43
- ### ES Module Usage
44
-
45
- ```js
46
- import { connect } from '@gemigo/extension-sdk';
47
-
48
- const gemigo = await connect();
49
- const pageInfo = await gemigo.getPageInfo();
50
- ```
51
-
52
34
  ## API Reference
53
35
 
54
- ### `connect(): Promise<GemigoExtension>`
55
-
56
- Connect to the GemiGo extension host. Must be called before using any SDK methods.
57
-
58
- ### Page APIs
36
+ ### Page Content Reading
59
37
 
60
38
  | Method | Description |
61
39
  |--------|-------------|
@@ -64,49 +42,73 @@ Connect to the GemiGo extension host. Must be called before using any SDK method
64
42
  | `getPageText()` | Get page text content |
65
43
  | `getSelection()` | Get selected text |
66
44
  | `extractArticle()` | Extract article title, content, excerpt |
45
+ | `extractLinks()` | Extract all links from page |
46
+ | `extractImages()` | Extract all images from page |
47
+ | `queryElement(selector, limit?)` | Query elements by CSS selector |
48
+
49
+ ### Page Manipulation
50
+
51
+ | Method | Description |
52
+ |--------|-------------|
53
+ | `highlight(selector, color?)` | Highlight elements (returns highlightId) |
54
+ | `removeHighlight(highlightId)` | Remove highlight |
55
+ | `insertWidget(html, position)` | Insert floating widget |
56
+ | `updateWidget(widgetId, html)` | Update widget content |
57
+ | `removeWidget(widgetId)` | Remove widget |
58
+ | `injectCSS(css)` | Inject CSS (returns styleId) |
59
+ | `removeCSS(styleId)` | Remove injected CSS |
67
60
 
68
- ### Action APIs
61
+ ### Screenshots
69
62
 
70
63
  | Method | Description |
71
64
  |--------|-------------|
72
- | `highlight(selector, color?)` | Highlight elements on page |
73
- | `notify(title, message)` | Send system notification |
74
- | `captureVisible()` | Capture screenshot of visible tab |
65
+ | `captureVisible()` | Capture visible area screenshot |
75
66
 
76
- ### Event APIs
67
+ ### Events
77
68
 
78
69
  | Method | Description |
79
70
  |--------|-------------|
80
- | `on('contextMenu', handler)` | Subscribe to context menu events |
81
- | `off('contextMenu', handler?)` | Unsubscribe from events |
71
+ | `onContextMenu(handler)` | Subscribe to context menu events |
82
72
  | `getContextMenuEvent()` | Get pending context menu event |
83
73
 
84
- ## Example: Translation App
74
+ ### Common APIs
75
+
76
+ | Method | Description |
77
+ |--------|-------------|
78
+ | `gemigo.notify(title, message)` | Send system notification |
79
+
80
+ ## Example: Translation Bubble
85
81
 
86
82
  ```html
87
- <!DOCTYPE html>
88
- <html>
89
- <head>
90
- <title>Translation App</title>
91
- </head>
92
- <body>
93
- <div id="result"></div>
94
-
95
- <script src="https://unpkg.com/@gemigo/extension-sdk/dist/gemigo-extension-sdk.umd.js"></script>
96
- <script>
97
- GemigoExtensionSDK.connect().then(async (gemigo) => {
98
- // Handle context menu "Translate" action
99
- gemigo.on('contextMenu', async (event) => {
100
- if (event.menuId === 'translate' && event.selectionText) {
101
- // Your translation logic here
102
- document.getElementById('result').textContent =
103
- `Translating: ${event.selectionText}`;
104
- }
105
- });
106
- });
107
- </script>
108
- </body>
109
- </html>
83
+ <script src="https://unpkg.com/@gemigo/extension-sdk/dist/gemigo-extension-sdk.umd.js"></script>
84
+ <script>
85
+ gemigo.extension.onContextMenu(async (event) => {
86
+ if (event.selectionText) {
87
+ const translated = await translateText(event.selectionText);
88
+
89
+ // Show translation bubble on page
90
+ await gemigo.extension.insertWidget(
91
+ `<div style="background:#667eea;color:#fff;padding:16px;border-radius:12px;">
92
+ ${translated}
93
+ </div>`,
94
+ 'bottom-right'
95
+ );
96
+ }
97
+ });
98
+ </script>
99
+ ```
100
+
101
+ ## Example: Reader Mode
102
+
103
+ ```javascript
104
+ // Inject reader-friendly CSS
105
+ const { styleId } = await gemigo.extension.injectCSS(`
106
+ body { max-width: 720px; margin: 0 auto; font-family: Georgia, serif; }
107
+ nav, aside, .ads { display: none !important; }
108
+ `);
109
+
110
+ // Remove later
111
+ await gemigo.extension.removeCSS(styleId);
110
112
  ```
111
113
 
112
114
  ## License
@@ -0,0 +1,155 @@
1
+ import { ContextMenuEvent, ContextMenuEventResult, CaptureResult } from '../types';
2
+ /** Widget insertion result */
3
+ export interface WidgetResult {
4
+ success: boolean;
5
+ widgetId?: string;
6
+ error?: string;
7
+ }
8
+ /** CSS injection result */
9
+ export interface CSSResult {
10
+ success: boolean;
11
+ styleId?: string;
12
+ error?: string;
13
+ }
14
+ /** Highlight result with cleanup ID */
15
+ export interface HighlightResult {
16
+ success: boolean;
17
+ count?: number;
18
+ highlightId?: string;
19
+ }
20
+ /**
21
+ * Extension API object
22
+ */
23
+ export declare const extensionAPI: {
24
+ /**
25
+ * Get current page info
26
+ */
27
+ getPageInfo: () => Promise<{
28
+ url: string;
29
+ title: string;
30
+ favIconUrl?: string;
31
+ }>;
32
+ /**
33
+ * Get full page HTML
34
+ */
35
+ getPageHTML: () => Promise<string>;
36
+ /**
37
+ * Get page text content
38
+ */
39
+ getPageText: () => Promise<string>;
40
+ /**
41
+ * Get selected text
42
+ */
43
+ getSelection: () => Promise<string>;
44
+ /**
45
+ * Extract article content
46
+ */
47
+ extractArticle: () => Promise<{
48
+ success: boolean;
49
+ title?: string;
50
+ content?: string;
51
+ excerpt?: string;
52
+ url?: string;
53
+ }>;
54
+ /**
55
+ * Highlight elements matching selector
56
+ * @returns Result with highlightId for cleanup
57
+ */
58
+ highlight: (selector: string, color?: string) => Promise<HighlightResult>;
59
+ /**
60
+ * Remove highlight by ID
61
+ */
62
+ removeHighlight: (highlightId: string) => Promise<{
63
+ success: boolean;
64
+ }>;
65
+ /**
66
+ * Insert a widget (floating element) in the page
67
+ * @param html - HTML content of the widget
68
+ * @param position - 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | { x, y }
69
+ */
70
+ insertWidget: (html: string, position?: string | {
71
+ x: number;
72
+ y: number;
73
+ }) => Promise<WidgetResult>;
74
+ /**
75
+ * Update widget content
76
+ */
77
+ updateWidget: (widgetId: string, html: string) => Promise<{
78
+ success: boolean;
79
+ error?: string;
80
+ }>;
81
+ /**
82
+ * Remove a widget
83
+ */
84
+ removeWidget: (widgetId: string) => Promise<{
85
+ success: boolean;
86
+ }>;
87
+ /**
88
+ * Inject CSS into the page
89
+ * @returns Result with styleId for cleanup
90
+ */
91
+ injectCSS: (css: string) => Promise<CSSResult>;
92
+ /**
93
+ * Remove injected CSS by ID
94
+ */
95
+ removeCSS: (styleId: string) => Promise<{
96
+ success: boolean;
97
+ }>;
98
+ /**
99
+ * Extract all links from the page
100
+ */
101
+ extractLinks: () => Promise<{
102
+ success: boolean;
103
+ links?: {
104
+ href: string;
105
+ text: string;
106
+ title?: string;
107
+ }[];
108
+ error?: string;
109
+ }>;
110
+ /**
111
+ * Extract all images from the page
112
+ */
113
+ extractImages: () => Promise<{
114
+ success: boolean;
115
+ images?: {
116
+ src: string;
117
+ alt?: string;
118
+ width?: number;
119
+ height?: number;
120
+ }[];
121
+ error?: string;
122
+ }>;
123
+ /**
124
+ * Query elements by CSS selector
125
+ * @param selector - CSS selector
126
+ * @param limit - Max number of results (default 100)
127
+ */
128
+ queryElement: (selector: string, limit?: number) => Promise<{
129
+ success: boolean;
130
+ elements?: {
131
+ tagName: string;
132
+ text: string;
133
+ attributes: Record<string, string>;
134
+ }[];
135
+ count?: number;
136
+ error?: string;
137
+ }>;
138
+ /**
139
+ * Capture visible area
140
+ */
141
+ captureVisible: () => Promise<CaptureResult>;
142
+ /**
143
+ * Get pending context menu event
144
+ */
145
+ getContextMenuEvent: () => Promise<ContextMenuEventResult>;
146
+ /**
147
+ * Register context menu event handler
148
+ */
149
+ onContextMenu: (handler: (event: ContextMenuEvent) => void) => (() => void);
150
+ /**
151
+ * Register selection change event handler
152
+ * @returns Unsubscribe function
153
+ */
154
+ onSelectionChange: (handler: (selection: string, url?: string) => void) => (() => void);
155
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * API module exports
3
+ */
4
+ export { extensionAPI } from './extension';
@@ -0,0 +1,117 @@
1
+ import { AsyncMethodReturns } from 'penpal';
2
+ import { ContextMenuEvent } from '../types';
3
+ /**
4
+ * Host methods interface - what the extension provides to apps
5
+ */
6
+ export interface HostMethods {
7
+ getPageInfo(): Promise<{
8
+ url: string;
9
+ title: string;
10
+ favIconUrl?: string;
11
+ }>;
12
+ getPageHTML(): Promise<string>;
13
+ getPageText(): Promise<string>;
14
+ getSelection(): Promise<string>;
15
+ highlight(selector: string, color?: string): Promise<{
16
+ success: boolean;
17
+ count?: number;
18
+ highlightId?: string;
19
+ }>;
20
+ removeHighlight(highlightId: string): Promise<{
21
+ success: boolean;
22
+ }>;
23
+ insertWidget(config: {
24
+ html: string;
25
+ position: string | {
26
+ x: number;
27
+ y: number;
28
+ };
29
+ }): Promise<{
30
+ success: boolean;
31
+ widgetId?: string;
32
+ error?: string;
33
+ }>;
34
+ updateWidget(widgetId: string, html: string): Promise<{
35
+ success: boolean;
36
+ error?: string;
37
+ }>;
38
+ removeWidget(widgetId: string): Promise<{
39
+ success: boolean;
40
+ }>;
41
+ injectCSS(css: string): Promise<{
42
+ success: boolean;
43
+ styleId?: string;
44
+ error?: string;
45
+ }>;
46
+ removeCSS(styleId: string): Promise<{
47
+ success: boolean;
48
+ }>;
49
+ notify(options: {
50
+ title: string;
51
+ message: string;
52
+ }): Promise<{
53
+ success: boolean;
54
+ }>;
55
+ captureVisible(): Promise<{
56
+ success: boolean;
57
+ dataUrl?: string;
58
+ error?: string;
59
+ }>;
60
+ extractArticle(): Promise<{
61
+ success: boolean;
62
+ title?: string;
63
+ content?: string;
64
+ excerpt?: string;
65
+ url?: string;
66
+ }>;
67
+ extractLinks(): Promise<{
68
+ success: boolean;
69
+ links?: {
70
+ href: string;
71
+ text: string;
72
+ title?: string;
73
+ }[];
74
+ error?: string;
75
+ }>;
76
+ extractImages(): Promise<{
77
+ success: boolean;
78
+ images?: {
79
+ src: string;
80
+ alt?: string;
81
+ width?: number;
82
+ height?: number;
83
+ }[];
84
+ error?: string;
85
+ }>;
86
+ queryElement(selector: string, limit?: number): Promise<{
87
+ success: boolean;
88
+ elements?: {
89
+ tagName: string;
90
+ text: string;
91
+ attributes: Record<string, string>;
92
+ }[];
93
+ count?: number;
94
+ error?: string;
95
+ }>;
96
+ getContextMenuEvent(): Promise<{
97
+ success: boolean;
98
+ event?: ContextMenuEvent;
99
+ }>;
100
+ }
101
+ /**
102
+ * Child methods interface - what apps expose to the extension host
103
+ */
104
+ export interface ChildMethods {
105
+ onContextMenuEvent(event: ContextMenuEvent): void;
106
+ }
107
+ /**
108
+ * Get or create connection to parent (extension host)
109
+ *
110
+ * @param childMethods - Methods to expose to parent
111
+ * @returns Promise resolving to host methods
112
+ */
113
+ export declare function getHost(childMethods?: ChildMethods): Promise<AsyncMethodReturns<HostMethods>>;
114
+ /**
115
+ * Initialize connection immediately (for faster first call)
116
+ */
117
+ export declare function initConnection(childMethods?: ChildMethods): void;
@@ -0,0 +1,35 @@
1
+ import { ContextMenuEvent } from '../types';
2
+ /** Selection change event */
3
+ export interface SelectionChangeEvent {
4
+ selection: string;
5
+ url?: string;
6
+ }
7
+ /** Event handler type map */
8
+ export interface EventHandlerMap {
9
+ contextMenu: (event: ContextMenuEvent) => void;
10
+ selectionChange: (selection: string, url?: string) => void;
11
+ }
12
+ /** Event names */
13
+ export type EventName = keyof EventHandlerMap;
14
+ /**
15
+ * Register an event handler
16
+ *
17
+ * @param event - Event name
18
+ * @param handler - Handler function
19
+ * @returns Unsubscribe function
20
+ */
21
+ export declare function on<K extends EventName>(event: K, handler: EventHandlerMap[K]): () => void;
22
+ /**
23
+ * Emit an event to all registered handlers
24
+ *
25
+ * @param event - Event name
26
+ * @param data - Event data
27
+ */
28
+ export declare function emit<K extends EventName>(event: K, data: Parameters<EventHandlerMap[K]>[0]): void;
29
+ /**
30
+ * Get child methods that connect events to the bus
31
+ */
32
+ export declare function getChildMethods(): {
33
+ onContextMenuEvent(event: ContextMenuEvent): void;
34
+ onSelectionChange(selection: string, url?: string): void;
35
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Core module exports
3
+ */
4
+ export { getHost, initConnection } from './connection';
5
+ export type { HostMethods, ChildMethods } from './connection';
6
+ export { on, emit, getChildMethods } from './event-bus';
7
+ export type { EventHandlerMap, EventName } from './event-bus';