auto-component 0.0.33 → 0.0.34

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.jsx +232 -48
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auto-component",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "main": "src/index.jsx",
5
5
  "peerDependencies": {
6
6
  "react": "^18.2.0",
package/src/index.jsx CHANGED
@@ -1,66 +1,250 @@
1
- import {useState, useEffect} from 'react'
2
- import { Link } from 'react-router-dom'
3
- import { getPeople } from '../../utilities/people-service'
4
- import './People.css'
5
- import NewPersonForm from './NewPersonForm'
6
- import AutoComponent from '../../components/Componenter'
1
+ import { useState, useEffect } from 'react'
2
+ // import beautify from 'js-beautify';
3
+ import './auto-component.css'
7
4
 
8
- const People = () => {
9
- const [isLoading, setIsLoading] = useState(true)
10
- const [people, setPeople] = useState([])
5
+ const AutoComponent = ({ exclusions }) => {
11
6
 
7
+ //**-----------**/
8
+ // ** State ** //
9
+ //**---------**/
10
+ const [ currentHtml, setHtml ] = useState('')
11
+ const [ currentStyle, setStyles ] = useState('')
12
+ const [ currentRequest, setRequest ] = useState('')
13
+ const [ user, setUser ] = useState('')
14
+
15
+ const [ responseData, setResponseData ] = useState(null)
16
+ const [ requestData, setRequestData ] = useState(null)
17
+
18
+ const [ activeTab, setActiveTab ] = useState('')
19
+ const [ history, setHistory ] = useState(["No History"])
20
+
21
+ //**-------------------------**/
22
+ // ** HTML/CSS Formatting ** //
23
+ //**-----------------------**/
24
+ // get the html/style for the current page and set state
25
+ const htmlContent = () => {
26
+ const body = document.querySelector('body')
27
+ const htmlContent = body ? body.innerHTML : ''
28
+ const cssStyles = document.documentElement.innerHTML
29
+
30
+ const cleanedHtml = cleanExclusions(htmlContent, exclusions)
31
+ const cleanedStyles = cleanStyles(cssStyles)
32
+
33
+ setHtml(cleanedHtml)
34
+ setStyles(cleanedStyles)
35
+ }
36
+
37
+ // format html for display (breaks/indentation)
38
+ // const formatHtml = (html) => {
39
+ // return beautify.html(html, {
40
+ // indent_size: 2,
41
+ // wrap_line_length: 80,
42
+ // max_preserve_newlines: 1,
43
+ // })
44
+ // }
45
+
46
+ // clean html of exclusions:
47
+ // if an element className includes 'exclude'
48
+ // (partial) the element wrapper remains, but contents removed
49
+ // OR, (full) the element and it's content are excluded from output
50
+
51
+ // partial exclusion
52
+ const cleanExclusions = (html) => {
53
+ const regexExcludeClass = /(<[^>]*\sclass\s*=\s*['"]([^'"]*exclude[^'"]*)['"][^>]*>)[\s\S]*?(<\/[^>]*>)/g;
54
+ const cleanedHtml = html.replace(regexExcludeClass, '$1$3');
55
+ const scriptIndex = cleanedHtml.lastIndexOf('<script');
56
+
57
+ // return formatHtml(cleanedHtml.substring(0, scriptIndex));
58
+ return cleanedHtml.substring(0, scriptIndex);
59
+ };
60
+
61
+ // full exclusion
62
+ // const cleanExclusionsFull = (html) => {
63
+ // const regexExcludeClass = /<[^>]*\sclass\s*=\s*['"]([^'"]*exclude[^'"]*)['"][^>]*>[\s\S]*?<\/[^>]*>/g
64
+ // const cleanedHtml = html.replace(regexExcludeClass, '')
65
+ // const scriptIndex = cleanedHtml.lastIndexOf('<script')
66
+ //
67
+ // return formatHtml(cleanedHtml.substring(0, scriptIndex))
68
+ // }
69
+
70
+ // exclude non <style> data and remove comments
71
+ const cleanStyles = (css) => {
72
+ const styleRegex = /<style\b[^>]*>(.*?)<\/style>/gs
73
+ const matches = css.match(styleRegex)
74
+
75
+ if (matches) {
76
+ const cleanedMatches = matches.map(match => match.replace(/\/\*[\s\S]*?\*\//g, ''))
77
+ return cleanedMatches
78
+ }
79
+ return null
80
+ }
81
+
82
+ const randomUser = () => {
83
+ setUser(Math.floor(Math.random()*100000))
84
+ }
85
+
86
+ useEffect(() => {
87
+ htmlContent()
88
+ randomUser()
89
+ }, [])
90
+
91
+ //**---------------------------**/
92
+ // ** API Requests/Response ** //
93
+ //**-------------------------**/
94
+
95
+ // TEMP FUNCTION FOR TESTING
96
+ // const sendRequest = (data) => {
97
+ // return(response)
98
+ // }
99
+
100
+ const sendRequest = async () => {
101
+ const url = "https://server-auto-component-46830ff262f8.herokuapp.com/api";
102
+
103
+ try {
104
+ const res = await fetch(url, {
105
+ method: 'POST',
106
+ headers: {
107
+ 'Content-Type': 'application/json',
108
+ },
109
+ body: JSON.stringify(requestData),
110
+ });
111
+
112
+ if (res.ok) {
113
+ const jsonData = await res.json();
114
+ return jsonData;
115
+ } else {
116
+ throw new Error("Invalid request!");
117
+ }
118
+ } catch (err) {
119
+ console.log(err.message);
120
+ }
121
+ };
122
+
123
+ // make API request with updated state data
12
124
  const handleRequest = async () => {
13
125
  try {
14
- const peopleData = await getPeople()
15
- if (peopleData) setPeople(peopleData)
126
+ const resData = await sendRequest();
127
+
128
+ if (resData) {
129
+ setHistory(resData.history)
130
+ // setResponseData(formatHtml(resData.response.content));
131
+ setResponseData(resData.response.content);
132
+ setActiveTab('response');
133
+ }
16
134
  } catch (err) {
17
- console.log(err)
135
+ console.log(err);
18
136
  }
19
- setIsLoading(false)
137
+ // setIsLoading(false);
138
+ };
139
+
140
+ //**------------------------**/
141
+ // ** UI/Button Handling ** //
142
+ //**----------------------**/
143
+
144
+ const handleChange = (e) => {
145
+ e.preventDefault()
146
+ setRequest(e.target.value)
147
+ }
148
+
149
+ const handleGenerate = async (e) => {
150
+ console.log(currentHtml)
151
+ await setRequestData({
152
+ "userId": user,
153
+ "request": currentRequest,
154
+ "html": currentHtml
155
+ })
20
156
  }
21
157
 
22
158
  useEffect(() => {
23
- handleRequest()
24
- }, [])
159
+ if (requestData !== null) {
160
+ handleRequest();
161
+ }
162
+ },[requestData])
163
+
164
+ const handleReset = () => {
165
+ setRequest('')
166
+ setResponseData('')
167
+ randomUser()
168
+ setHistory([])
169
+ }
170
+
171
+ const handleRequestTab = async () => {
172
+ await setActiveTab(activeTab === 'response' || activeTab === '' ? 'request' : '');
173
+ }
174
+
175
+ const handleResponseTab = async () => {
176
+ await setActiveTab(activeTab === 'request' || activeTab === '' ? 'response' : '');
177
+ }
25
178
 
179
+ const copyToClipboard = async () => {
180
+ const text = activeTab === 'response' ? responseData : requestData
181
+ await navigator.clipboard.writeText(text)
182
+ }
183
+
184
+ //**---------------**/
185
+ // ** Rendering ** //
186
+ //**-------------**/
26
187
 
27
- if (isLoading) {
28
- return <h1>Loading...</h1>;
29
- } else {
188
+ const getLog = () => {
30
189
  return (
31
- <section>
32
- {/* <NewPersonForm handleRequest={handleRequest} /> */}
190
+ history.map((entry, index) => (
191
+
192
+ index !== 0 && entry.content.split('HTML Context:')[0] + (entry.content.includes("User Request") ? '\n' : '\n\n\n')
193
+ )
194
+ ))
195
+ }
33
196
 
34
- <div id="secret-element" className='secret secret-element'>
35
- this is the excluded text
36
- <div className='something'>
37
- and this is the excluded element
38
- </div>
39
- </div>
197
+ const requestHTML = currentHtml ? (
198
+ `Review the details below for accuracy and privacy concerns.
199
+ If the contents of an element should be excluded, add the 'exclude' class to the element.
200
+ Click Generate to send the request and receive the auto component AI generated code.
40
201
 
41
- <div id="not-secret-element" className=''>
42
- included
43
- </div>
202
+ User ID:\n `
203
+ + user
204
+ + "\n\nUser Request:\n"
205
+ + currentRequest
206
+ + "\n\nUser HTML:\n"
207
+ + currentHtml
208
+ ) : 'There was an error collecting your HTML. Ensure no top level elements are assigned the class "exclude"'
209
+
210
+ const responseHtml = responseData ? (
211
+ responseData
212
+ ) : 'No response has been generated'
44
213
 
45
- <div className="people-list">
46
- {people.map((p) => (
47
- <Link to={"/people/" + p._id}>
48
- <div key={p._id}>
49
- <h3>{p.name}</h3>
50
- <img
51
- className="profile-image"
52
- src={p.image}
53
- alt={`Image of ${p.name}`}
54
- />
55
- <p>{p.title}</p>
56
- </div>
57
- </Link>
58
- ))}
214
+
215
+ return (
216
+ <>
217
+ {/* create the display window */}
218
+ <div id="auto-component">
219
+ <div>
220
+ <p>test</p>
59
221
  </div>
60
- <AutoComponent />
61
- </section>
62
- );
63
- }
222
+ <div id="auto-component-code" className={`${!activeTab ? 'hidden' : ''} auto-component-code`}>
223
+ <pre>
224
+ {activeTab === 'request' ? getLog() : responseHtml}
225
+ </pre>
226
+ </div>
227
+ <div id="auto-component-entry">
228
+ <input type="text" value={currentRequest} onChange={handleChange} placeholder="Enter a request"></input>
229
+ <button onClick={handleGenerate}>Generate</button>
230
+ <button onClick={handleReset}>X</button>
231
+ </div>
232
+ <div>
233
+ <div id='auto-component-tabs'>
234
+ <div className={`${activeTab === 'request' ? 'selected' : ''} tab`} onClick={handleRequestTab}>
235
+ Request
236
+ </div>
237
+ <div className={`${activeTab === 'response' ? 'selected' : ''} tab`} onClick={handleResponseTab}>
238
+ Response
239
+ </div>
240
+ </div>
241
+ </div>
242
+ <div className="auto-component-copy" onClick={copyToClipboard} style={activeTab !== 'response' ? { display: 'none' } : null}>
243
+ copy
244
+ </div>
245
+ </div>
246
+ </>
247
+ )
64
248
  }
65
249
 
66
- export default People
250
+ export default AutoComponent