refactor: consolidate all Node.js development into lib package
- Move scripts/ to lib/scripts/ and convert to ESM modules - Consolidate dependencies: add live-server to lib/package.json - Remove root package.json and node_modules split - Preserve CLI integration via existing rebuild-library.sh - Add development quickstart guide for new unified workflow - Clean up outdated file references and duplicate assets
This commit is contained in:
39
DEVELOPMENT_QUICKSTART.md
Normal file
39
DEVELOPMENT_QUICKSTART.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Insertr Development Quickstart
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
- `lib/` - JavaScript library development (all Node.js tooling)
|
||||||
|
- `insertr-cli/` - Go CLI application
|
||||||
|
- `demo-site/` - Static HTML demo site
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Library Development
|
||||||
|
```bash
|
||||||
|
cd lib/
|
||||||
|
npm install
|
||||||
|
npm run serve # Start development server
|
||||||
|
npm run check # Validate setup
|
||||||
|
npm run demo # Show demo instructions
|
||||||
|
```
|
||||||
|
|
||||||
|
### CLI Development
|
||||||
|
```bash
|
||||||
|
cd insertr-cli/
|
||||||
|
air # Hot reload development server
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Everything
|
||||||
|
```bash
|
||||||
|
cd lib/
|
||||||
|
npm run build:all # Builds library + CLI with embedded assets
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The CLI embeds the JavaScript library at build time for distribution. During development:
|
||||||
|
- `lib/` contains the JavaScript library source and build tools
|
||||||
|
- Air (Go hot reload) watches `lib/src/` and rebuilds when library changes
|
||||||
|
- Demo site served from `lib/` package for unified development experience
|
||||||
|
|
||||||
|
All Node.js dependencies and scripts are now consolidated in the `lib/` package.
|
||||||
5
TODO.md
5
TODO.md
@@ -100,6 +100,9 @@ Bring the current library (`lib/`) up to feature parity with the archived protot
|
|||||||
- [ ] Adaptive modal sizing and positioning
|
- [ ] Adaptive modal sizing and positioning
|
||||||
- [ ] Touch-optimized hover states
|
- [ ] Touch-optimized hover states
|
||||||
|
|
||||||
|
#### 3.3 Server / CLI
|
||||||
|
- [ ] A better way to inject insertr.js library into our CLI. Maybe use a cdn when library is stable.
|
||||||
|
|
||||||
## Key Files to Port/Adapt
|
## Key Files to Port/Adapt
|
||||||
|
|
||||||
### From Prototype (`demo-site/archive/insertr-old/`)
|
### From Prototype (`demo-site/archive/insertr-old/`)
|
||||||
@@ -143,4 +146,4 @@ Keep the current library + CLI architecture while porting prototype features:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This TODO represents bringing a basic proof-of-concept up to production-ready feature parity with the original prototype.*
|
*This TODO represents bringing a basic proof-of-concept up to production-ready feature parity with the original prototype.*
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
var Insertr = (function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* InsertrCore - Core functionality for content management
|
|
||||||
*/
|
|
||||||
class InsertrCore {
|
|
||||||
constructor(options = {}) {
|
|
||||||
this.options = {
|
|
||||||
apiEndpoint: options.apiEndpoint || '/api/content',
|
|
||||||
siteId: options.siteId || 'default',
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all enhanced elements on the page
|
|
||||||
findEnhancedElements() {
|
|
||||||
return document.querySelectorAll('[data-insertr-enhanced="true"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get element metadata
|
|
||||||
getElementMetadata(element) {
|
|
||||||
return {
|
|
||||||
contentId: element.getAttribute('data-content-id'),
|
|
||||||
contentType: element.getAttribute('data-content-type'),
|
|
||||||
element: element
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all elements with their metadata
|
|
||||||
getAllElements() {
|
|
||||||
const elements = this.findEnhancedElements();
|
|
||||||
return Array.from(elements).map(el => this.getElementMetadata(el));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* InsertrEditor - Visual editing functionality
|
|
||||||
*/
|
|
||||||
class InsertrEditor {
|
|
||||||
constructor(core, options = {}) {
|
|
||||||
this.core = core;
|
|
||||||
this.options = options;
|
|
||||||
this.isActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
if (this.isActive) return;
|
|
||||||
|
|
||||||
console.log('🚀 Starting Insertr Editor');
|
|
||||||
this.isActive = true;
|
|
||||||
|
|
||||||
// Add editor styles
|
|
||||||
this.addEditorStyles();
|
|
||||||
|
|
||||||
// Initialize all enhanced elements
|
|
||||||
const elements = this.core.getAllElements();
|
|
||||||
console.log(`📝 Found ${elements.length} editable elements`);
|
|
||||||
|
|
||||||
elements.forEach(meta => this.initializeElement(meta));
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeElement(meta) {
|
|
||||||
const { element, contentId, contentType } = meta;
|
|
||||||
|
|
||||||
// Add visual indicators
|
|
||||||
element.style.cursor = 'pointer';
|
|
||||||
element.style.position = 'relative';
|
|
||||||
|
|
||||||
// Add interaction handlers
|
|
||||||
this.addHoverEffects(element);
|
|
||||||
this.addClickHandler(element, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
addHoverEffects(element) {
|
|
||||||
element.addEventListener('mouseenter', () => {
|
|
||||||
element.classList.add('insertr-editing-hover');
|
|
||||||
});
|
|
||||||
|
|
||||||
element.addEventListener('mouseleave', () => {
|
|
||||||
element.classList.remove('insertr-editing-hover');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addClickHandler(element, meta) {
|
|
||||||
element.addEventListener('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.openEditor(meta);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
openEditor(meta) {
|
|
||||||
const { contentId, contentType, element } = meta;
|
|
||||||
const currentContent = element.textContent.trim();
|
|
||||||
|
|
||||||
// For now, use a simple prompt (will be replaced with proper modal)
|
|
||||||
const newContent = prompt(
|
|
||||||
`Edit ${contentType} content (ID: ${contentId}):`,
|
|
||||||
currentContent
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newContent !== null && newContent !== currentContent) {
|
|
||||||
this.updateContent(meta, newContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateContent(meta, newContent) {
|
|
||||||
const { element } = meta;
|
|
||||||
|
|
||||||
// Update the element content
|
|
||||||
element.textContent = newContent;
|
|
||||||
|
|
||||||
// TODO: Save to backend API
|
|
||||||
console.log(`💾 Content updated:`, meta.contentId, newContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
addEditorStyles() {
|
|
||||||
const styles = `
|
|
||||||
.insertr-editing-hover {
|
|
||||||
outline: 2px dashed #007cba !important;
|
|
||||||
outline-offset: 2px !important;
|
|
||||||
background-color: rgba(0, 124, 186, 0.05) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-insertr-enhanced="true"]:hover::after {
|
|
||||||
content: "✏️ " attr(data-content-type);
|
|
||||||
position: absolute;
|
|
||||||
top: -25px;
|
|
||||||
left: 0;
|
|
||||||
background: #007cba;
|
|
||||||
color: white;
|
|
||||||
padding: 2px 6px;
|
|
||||||
font-size: 11px;
|
|
||||||
border-radius: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
z-index: 1000;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const styleSheet = document.createElement('style');
|
|
||||||
styleSheet.type = 'text/css';
|
|
||||||
styleSheet.innerHTML = styles;
|
|
||||||
document.head.appendChild(styleSheet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insertr - The Tailwind of CMS
|
|
||||||
* Main library entry point
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Create global Insertr instance
|
|
||||||
window.Insertr = {
|
|
||||||
// Core functionality
|
|
||||||
core: null,
|
|
||||||
editor: null,
|
|
||||||
|
|
||||||
// Initialize the library
|
|
||||||
init(options = {}) {
|
|
||||||
console.log('🔧 Insertr v1.0.0 initializing...');
|
|
||||||
|
|
||||||
this.core = new InsertrCore(options);
|
|
||||||
this.editor = new InsertrEditor(this.core, options);
|
|
||||||
|
|
||||||
// Auto-initialize if DOM is ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => this.start());
|
|
||||||
} else {
|
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Start the editor
|
|
||||||
start() {
|
|
||||||
if (this.editor) {
|
|
||||||
this.editor.start();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Version info
|
|
||||||
version: '1.0.0'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Auto-initialize in development mode
|
|
||||||
if (document.querySelector('[data-insertr-enhanced]')) {
|
|
||||||
window.Insertr.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
var index = window.Insertr;
|
|
||||||
|
|
||||||
return index;
|
|
||||||
|
|
||||||
})();
|
|
||||||
1
insertr-cli/assets/lib/insertr.min.js
vendored
1
insertr-cli/assets/lib/insertr.min.js
vendored
@@ -1 +0,0 @@
|
|||||||
var Insertr=function(){"use strict";class t{constructor(t={}){this.options={apiEndpoint:t.apiEndpoint||"/api/content",siteId:t.siteId||"default",...t}}findEnhancedElements(){return document.querySelectorAll('[data-insertr-enhanced="true"]')}getElementMetadata(t){return{contentId:t.getAttribute("data-content-id"),contentType:t.getAttribute("data-content-type"),element:t}}getAllElements(){const t=this.findEnhancedElements();return Array.from(t).map(t=>this.getElementMetadata(t))}}class e{constructor(t,e={}){this.core=t,this.options=e,this.isActive=!1}start(){if(this.isActive)return;console.log("🚀 Starting Insertr Editor"),this.isActive=!0,this.addEditorStyles();const t=this.core.getAllElements();console.log(`📝 Found ${t.length} editable elements`),t.forEach(t=>this.initializeElement(t))}initializeElement(t){const{element:e,contentId:n,contentType:i}=t;e.style.cursor="pointer",e.style.position="relative",this.addHoverEffects(e),this.addClickHandler(e,t)}addHoverEffects(t){t.addEventListener("mouseenter",()=>{t.classList.add("insertr-editing-hover")}),t.addEventListener("mouseleave",()=>{t.classList.remove("insertr-editing-hover")})}addClickHandler(t,e){t.addEventListener("click",t=>{t.preventDefault(),this.openEditor(e)})}openEditor(t){const{contentId:e,contentType:n,element:i}=t,o=i.textContent.trim(),r=prompt(`Edit ${n} content (ID: ${e}):`,o);null!==r&&r!==o&&this.updateContent(t,r)}updateContent(t,e){const{element:n}=t;n.textContent=e,console.log("💾 Content updated:",t.contentId,e)}addEditorStyles(){const t=document.createElement("style");t.type="text/css",t.innerHTML='\n .insertr-editing-hover {\n outline: 2px dashed #007cba !important;\n outline-offset: 2px !important;\n background-color: rgba(0, 124, 186, 0.05) !important;\n }\n \n [data-insertr-enhanced="true"]:hover::after {\n content: "✏️ " attr(data-content-type);\n position: absolute;\n top: -25px;\n left: 0;\n background: #007cba;\n color: white;\n padding: 2px 6px;\n font-size: 11px;\n border-radius: 3px;\n white-space: nowrap;\n z-index: 1000;\n font-family: monospace;\n }\n ',document.head.appendChild(t)}}return window.Insertr={core:null,editor:null,init(n={}){return console.log("🔧 Insertr v1.0.0 initializing..."),this.core=new t(n),this.editor=new e(this.core,n),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>this.start()):this.start(),this},start(){this.editor&&this.editor.start()},version:"1.0.0"},document.querySelector("[data-insertr-enhanced]")&&window.Insertr.init(),window.Insertr}();
|
|
||||||
@@ -15,7 +15,7 @@ var Insertr = (function () {
|
|||||||
|
|
||||||
// Find all enhanced elements on the page
|
// Find all enhanced elements on the page
|
||||||
findEnhancedElements() {
|
findEnhancedElements() {
|
||||||
return document.querySelectorAll('[data-insertr-enhanced="true"]');
|
return document.querySelectorAll('.insertr');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get element metadata
|
// Get element metadata
|
||||||
@@ -608,7 +608,7 @@ var Insertr = (function () {
|
|||||||
background-color: rgba(0, 124, 186, 0.05) !important;
|
background-color: rgba(0, 124, 186, 0.05) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-insertr-enhanced="true"]:hover::after {
|
.insertr:hover::after {
|
||||||
content: "✏️ " attr(data-content-type);
|
content: "✏️ " attr(data-content-type);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -25px;
|
top: -25px;
|
||||||
@@ -1142,16 +1142,16 @@ var Insertr = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hide editing interface when not in edit mode */
|
/* Hide editing interface when not in edit mode */
|
||||||
body:not(.insertr-edit-mode) [data-insertr-enhanced]:hover::after {
|
body:not(.insertr-edit-mode) .insertr:hover::after {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only show editing features when in edit mode */
|
/* Only show editing features when in edit mode */
|
||||||
.insertr-authenticated.insertr-edit-mode [data-insertr-enhanced] {
|
.insertr-authenticated.insertr-edit-mode .insertr {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-authenticated.insertr-edit-mode [data-insertr-enhanced]:hover {
|
.insertr-authenticated.insertr-edit-mode .insertr:hover {
|
||||||
outline: 2px dashed #007cba !important;
|
outline: 2px dashed #007cba !important;
|
||||||
outline-offset: 2px !important;
|
outline-offset: 2px !important;
|
||||||
background-color: rgba(0, 124, 186, 0.05) !important;
|
background-color: rgba(0, 124, 186, 0.05) !important;
|
||||||
@@ -1203,25 +1203,25 @@ var Insertr = (function () {
|
|||||||
core: null,
|
core: null,
|
||||||
editor: null,
|
editor: null,
|
||||||
auth: null,
|
auth: null,
|
||||||
|
|
||||||
// Initialize the library
|
// Initialize the library
|
||||||
init(options = {}) {
|
init(options = {}) {
|
||||||
console.log('🔧 Insertr v1.0.0 initializing... (Hot Reload Ready)');
|
console.log('🔧 Insertr v1.0.0 initializing... (Hot Reload Ready)');
|
||||||
|
|
||||||
this.core = new InsertrCore(options);
|
this.core = new InsertrCore(options);
|
||||||
this.auth = new InsertrAuth(options);
|
this.auth = new InsertrAuth(options);
|
||||||
this.editor = new InsertrEditor(this.core, this.auth, options);
|
this.editor = new InsertrEditor(this.core, this.auth, options);
|
||||||
|
|
||||||
// Auto-initialize if DOM is ready
|
// Auto-initialize if DOM is ready
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', () => this.start());
|
document.addEventListener('DOMContentLoaded', () => this.start());
|
||||||
} else {
|
} else {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Start the system - only creates the minimal trigger
|
// Start the system - only creates the minimal trigger
|
||||||
start() {
|
start() {
|
||||||
if (this.auth) {
|
if (this.auth) {
|
||||||
@@ -1236,37 +1236,36 @@ var Insertr = (function () {
|
|||||||
this.editor.start();
|
this.editor.start();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Public API methods
|
// Public API methods
|
||||||
login() {
|
login() {
|
||||||
return this.auth ? this.auth.toggleAuthentication() : null;
|
return this.auth ? this.auth.toggleAuthentication() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
if (this.auth && this.auth.isAuthenticated()) {
|
if (this.auth && this.auth.isAuthenticated()) {
|
||||||
this.auth.toggleAuthentication();
|
this.auth.toggleAuthentication();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleEditMode() {
|
toggleEditMode() {
|
||||||
return this.auth ? this.auth.toggleEditMode() : null;
|
return this.auth ? this.auth.toggleEditMode() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
isAuthenticated() {
|
isAuthenticated() {
|
||||||
return this.auth ? this.auth.isAuthenticated() : false;
|
return this.auth ? this.auth.isAuthenticated() : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
isEditMode() {
|
isEditMode() {
|
||||||
return this.auth ? this.auth.isEditMode() : false;
|
return this.auth ? this.auth.isEditMode() : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Version info
|
// TODO: Version info based on package.json?
|
||||||
version: '1.0.0'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auto-initialize in development mode with proper DOM ready handling
|
// Auto-initialize in development mode with proper DOM ready handling
|
||||||
function autoInitialize() {
|
function autoInitialize() {
|
||||||
if (document.querySelector('[data-insertr-enhanced="true"]')) {
|
if (document.querySelector('.insertr')) {
|
||||||
window.Insertr.init();
|
window.Insertr.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -126,11 +126,11 @@ func (i *Injector) injectLinkContent(node *html.Node, content string) {
|
|||||||
i.injectTextContent(node, content)
|
i.injectTextContent(node, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addContentAttributes adds necessary data attributes for editor functionality
|
// addContentAttributes adds necessary data attributes and insertr class for editor functionality
|
||||||
func (i *Injector) addContentAttributes(node *html.Node, contentID string, contentType string) {
|
func (i *Injector) addContentAttributes(node *html.Node, contentID string, contentType string) {
|
||||||
i.setAttribute(node, "data-content-id", contentID)
|
i.setAttribute(node, "data-content-id", contentID)
|
||||||
i.setAttribute(node, "data-content-type", contentType)
|
i.setAttribute(node, "data-content-type", contentType)
|
||||||
i.setAttribute(node, "data-insertr-enhanced", "true")
|
i.addClass(node, "insertr")
|
||||||
}
|
}
|
||||||
|
|
||||||
// InjectEditorAssets adds editor JavaScript and CSS to HTML document
|
// InjectEditorAssets adds editor JavaScript and CSS to HTML document
|
||||||
@@ -193,6 +193,48 @@ func (i *Injector) setAttribute(node *html.Node, key, value string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addClass safely adds a class to an HTML node
|
||||||
|
func (i *Injector) addClass(node *html.Node, className string) {
|
||||||
|
var classAttr *html.Attribute
|
||||||
|
var classIndex int = -1
|
||||||
|
|
||||||
|
// Find existing class attribute
|
||||||
|
for idx, attr := range node.Attr {
|
||||||
|
if attr.Key == "class" {
|
||||||
|
classAttr = &attr
|
||||||
|
classIndex = idx
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var classes []string
|
||||||
|
if classAttr != nil {
|
||||||
|
classes = strings.Fields(classAttr.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if class already exists
|
||||||
|
for _, class := range classes {
|
||||||
|
if class == className {
|
||||||
|
return // Class already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new class
|
||||||
|
classes = append(classes, className)
|
||||||
|
newClassValue := strings.Join(classes, " ")
|
||||||
|
|
||||||
|
if classIndex >= 0 {
|
||||||
|
// Update existing class attribute
|
||||||
|
node.Attr[classIndex].Val = newClassValue
|
||||||
|
} else {
|
||||||
|
// Add new class attribute
|
||||||
|
node.Attr = append(node.Attr, html.Attribute{
|
||||||
|
Key: "class",
|
||||||
|
Val: newClassValue,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Element represents a parsed HTML element with metadata
|
// Element represents a parsed HTML element with metadata
|
||||||
type Element struct {
|
type Element struct {
|
||||||
Node *html.Node
|
Node *html.Node
|
||||||
|
|||||||
2375
lib/package-lock.json
generated
2375
lib/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,12 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"watch": "rollup -c -w",
|
"watch": "rollup -c -w",
|
||||||
"dev": "rollup -c -w"
|
"dev": "rollup -c -w",
|
||||||
|
"serve": "node scripts/dev.js serve",
|
||||||
|
"serve:about": "live-server ../demo-site --port=3000 --open=/about.html",
|
||||||
|
"check": "node scripts/dev.js check",
|
||||||
|
"demo": "node scripts/dev.js demo",
|
||||||
|
"build:all": "node scripts/build.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cms",
|
"cms",
|
||||||
@@ -25,6 +30,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-node-resolve": "^15.0.0",
|
"@rollup/plugin-node-resolve": "^15.0.0",
|
||||||
"@rollup/plugin-terser": "^0.4.0",
|
"@rollup/plugin-terser": "^0.4.0",
|
||||||
"rollup": "^3.0.0"
|
"rollup": "^3.0.0",
|
||||||
|
"live-server": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,16 +5,16 @@
|
|||||||
* This ensures the CLI always has the latest library version embedded
|
* This ensures the CLI always has the latest library version embedded
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { execSync } = require('child_process');
|
import { execSync } from 'child_process';
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
|
|
||||||
console.log('🔨 Building Insertr library and CLI...\n');
|
console.log('🔨 Building Insertr library and CLI...\n');
|
||||||
|
|
||||||
// 1. Build the library
|
// 1. Build the library
|
||||||
console.log('📦 Building JavaScript library...');
|
console.log('📦 Building JavaScript library...');
|
||||||
try {
|
try {
|
||||||
execSync('npm run build', { cwd: './lib', stdio: 'inherit' });
|
execSync('npm run build', { stdio: 'inherit' });
|
||||||
console.log('✅ Library built successfully\n');
|
console.log('✅ Library built successfully\n');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Library build failed:', error.message);
|
console.error('❌ Library build failed:', error.message);
|
||||||
@@ -23,8 +23,8 @@ try {
|
|||||||
|
|
||||||
// 2. Copy built library to CLI assets
|
// 2. Copy built library to CLI assets
|
||||||
console.log('📁 Copying library to CLI assets...');
|
console.log('📁 Copying library to CLI assets...');
|
||||||
const srcDir = './lib/dist';
|
const srcDir = './dist';
|
||||||
const destDir = './insertr-cli/pkg/content/assets';
|
const destDir = '../insertr-cli/pkg/content/assets';
|
||||||
|
|
||||||
// Ensure destination directory exists
|
// Ensure destination directory exists
|
||||||
fs.mkdirSync(destDir, { recursive: true });
|
fs.mkdirSync(destDir, { recursive: true });
|
||||||
@@ -43,7 +43,7 @@ console.log('📁 Assets copied successfully\n');
|
|||||||
// 3. Build the CLI
|
// 3. Build the CLI
|
||||||
console.log('🔧 Building Go CLI...');
|
console.log('🔧 Building Go CLI...');
|
||||||
try {
|
try {
|
||||||
execSync('go build -o insertr', { cwd: './insertr-cli', stdio: 'inherit' });
|
execSync('go build -o insertr', { cwd: '../insertr-cli', stdio: 'inherit' });
|
||||||
console.log('✅ CLI built successfully\n');
|
console.log('✅ CLI built successfully\n');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ CLI build failed:', error.message);
|
console.error('❌ CLI build failed:', error.message);
|
||||||
@@ -55,4 +55,4 @@ console.log('📋 What was built:');
|
|||||||
console.log(' • JavaScript library (lib/dist/)');
|
console.log(' • JavaScript library (lib/dist/)');
|
||||||
console.log(' • Go CLI with embedded library (insertr-cli/insertr)');
|
console.log(' • Go CLI with embedded library (insertr-cli/insertr)');
|
||||||
console.log('\n🚀 Ready to use:');
|
console.log('\n🚀 Ready to use:');
|
||||||
console.log(' cd insertr-cli && ./insertr --help');
|
console.log(' cd ../insertr-cli && ./insertr --help');
|
||||||
@@ -5,9 +5,9 @@
|
|||||||
* Provides common development tasks and utilities
|
* Provides common development tasks and utilities
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { execSync, spawn } = require('child_process');
|
import { execSync, spawn } from 'child_process';
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
|
|
||||||
const commands = {
|
const commands = {
|
||||||
serve: {
|
serve: {
|
||||||
@@ -21,7 +21,7 @@ const commands = {
|
|||||||
console.log(' ✏️ Client: Click "Login as Client" → "Edit Mode: On"');
|
console.log(' ✏️ Client: Click "Login as Client" → "Edit Mode: On"');
|
||||||
console.log(' 🔧 Developer: View source to see integration\n');
|
console.log(' 🔧 Developer: View source to see integration\n');
|
||||||
|
|
||||||
spawn('npx', ['live-server', 'demo-site', '--port=3000', '--open=/index.html'], {
|
spawn('npx', ['live-server', '../demo-site', '--port=3000', '--open=/index.html'], {
|
||||||
stdio: 'inherit'
|
stdio: 'inherit'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -33,13 +33,13 @@ const commands = {
|
|||||||
console.log('🔍 Checking Insertr project status...\n');
|
console.log('🔍 Checking Insertr project status...\n');
|
||||||
|
|
||||||
// Check files exist
|
// Check files exist
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
'demo-site/index.html',
|
'../demo-site/index.html',
|
||||||
'demo-site/about.html',
|
'../demo-site/about.html',
|
||||||
'demo-site/insertr/insertr.js',
|
'dist/insertr.js',
|
||||||
'demo-site/insertr/insertr.css',
|
'dist/insertr.min.js',
|
||||||
'package.json'
|
'package.json'
|
||||||
];
|
];
|
||||||
|
|
||||||
let allGood = true;
|
let allGood = true;
|
||||||
|
|
||||||
@@ -56,17 +56,17 @@ const commands = {
|
|||||||
console.log('\n🎉 All core files present!');
|
console.log('\n🎉 All core files present!');
|
||||||
console.log('\n📊 Project stats:');
|
console.log('\n📊 Project stats:');
|
||||||
|
|
||||||
// Count editable elements
|
// Count editable elements
|
||||||
const indexContent = fs.readFileSync('demo-site/index.html', 'utf8');
|
const indexContent = fs.readFileSync('../demo-site/index.html', 'utf8');
|
||||||
const aboutContent = fs.readFileSync('demo-site/about.html', 'utf8');
|
const aboutContent = fs.readFileSync('../demo-site/about.html', 'utf8');
|
||||||
const insertrMatches = (indexContent + aboutContent).match(/class="insertr"/g) || [];
|
const insertrMatches = (indexContent + aboutContent).match(/class="insertr"/g) || [];
|
||||||
console.log(` 📝 Editable elements: ${insertrMatches.length}`);
|
console.log(` 📝 Editable elements: ${insertrMatches.length}`);
|
||||||
|
|
||||||
|
// Check library size
|
||||||
|
const libSize = fs.statSync('dist/insertr.js').size;
|
||||||
|
console.log(` 📦 Library size: ${(libSize / 1024).toFixed(1)}KB`);
|
||||||
|
|
||||||
// Check library size
|
console.log('\n🚀 Ready to develop! Run: npm run serve');
|
||||||
const libSize = fs.statSync('demo-site/insertr/insertr.js').size;
|
|
||||||
console.log(` 📦 Library size: ${(libSize / 1024).toFixed(1)}KB`);
|
|
||||||
|
|
||||||
console.log('\n🚀 Ready to develop! Run: npm run dev');
|
|
||||||
} else {
|
} else {
|
||||||
console.log('\n❌ Some files are missing. Please check your setup.');
|
console.log('\n❌ Some files are missing. Please check your setup.');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -78,7 +78,7 @@ const commands = {
|
|||||||
description: 'Show demo instructions',
|
description: 'Show demo instructions',
|
||||||
action: () => {
|
action: () => {
|
||||||
console.log('🎬 Insertr Demo Instructions\n');
|
console.log('🎬 Insertr Demo Instructions\n');
|
||||||
console.log('1. 🌐 Start server: npm run dev');
|
console.log('1. 🌐 Start server: npm run serve');
|
||||||
console.log('2. 👀 Customer view: Browse the site normally');
|
console.log('2. 👀 Customer view: Browse the site normally');
|
||||||
console.log('3. 🔑 Client login: Click "Login as Client"');
|
console.log('3. 🔑 Client login: Click "Login as Client"');
|
||||||
console.log('4. ✏️ Edit mode: Click "Edit Mode: Off" to enable editing');
|
console.log('4. ✏️ Edit mode: Click "Edit Mode: Off" to enable editing');
|
||||||
@@ -107,7 +107,7 @@ if (commands[command]) {
|
|||||||
console.log(` ${name.padEnd(12)} ${cmd.description}`);
|
console.log(` ${name.padEnd(12)} ${cmd.description}`);
|
||||||
});
|
});
|
||||||
console.log('\nUsage: node scripts/dev.js <command>');
|
console.log('\nUsage: node scripts/dev.js <command>');
|
||||||
console.log(' or: npm run dev:help\n');
|
console.log(' or: npm run check\n');
|
||||||
} else {
|
} else {
|
||||||
console.log(`❌ Unknown command: ${command}`);
|
console.log(`❌ Unknown command: ${command}`);
|
||||||
console.log('Run: node scripts/dev.js help');
|
console.log('Run: node scripts/dev.js help');
|
||||||
@@ -509,16 +509,16 @@ export class InsertrAuth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hide editing interface when not in edit mode */
|
/* Hide editing interface when not in edit mode */
|
||||||
body:not(.insertr-edit-mode) [data-insertr-enhanced]:hover::after {
|
body:not(.insertr-edit-mode) .insertr:hover::after {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only show editing features when in edit mode */
|
/* Only show editing features when in edit mode */
|
||||||
.insertr-authenticated.insertr-edit-mode [data-insertr-enhanced] {
|
.insertr-authenticated.insertr-edit-mode .insertr {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-authenticated.insertr-edit-mode [data-insertr-enhanced]:hover {
|
.insertr-authenticated.insertr-edit-mode .insertr:hover {
|
||||||
outline: 2px dashed #007cba !important;
|
outline: 2px dashed #007cba !important;
|
||||||
outline-offset: 2px !important;
|
outline-offset: 2px !important;
|
||||||
background-color: rgba(0, 124, 186, 0.05) !important;
|
background-color: rgba(0, 124, 186, 0.05) !important;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export class InsertrEditor {
|
|||||||
background-color: rgba(0, 124, 186, 0.05) !important;
|
background-color: rgba(0, 124, 186, 0.05) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-insertr-enhanced="true"]:hover::after {
|
.insertr:hover::after {
|
||||||
content: "✏️ " attr(data-content-type);
|
content: "✏️ " attr(data-content-type);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -25px;
|
top: -25px;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export class InsertrCore {
|
|||||||
|
|
||||||
// Find all enhanced elements on the page
|
// Find all enhanced elements on the page
|
||||||
findEnhancedElements() {
|
findEnhancedElements() {
|
||||||
return document.querySelectorAll('[data-insertr-enhanced="true"]');
|
return document.querySelectorAll('.insertr');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get element metadata
|
// Get element metadata
|
||||||
|
|||||||
@@ -14,25 +14,25 @@ window.Insertr = {
|
|||||||
core: null,
|
core: null,
|
||||||
editor: null,
|
editor: null,
|
||||||
auth: null,
|
auth: null,
|
||||||
|
|
||||||
// Initialize the library
|
// Initialize the library
|
||||||
init(options = {}) {
|
init(options = {}) {
|
||||||
console.log('🔧 Insertr v1.0.0 initializing... (Hot Reload Ready)');
|
console.log('🔧 Insertr v1.0.0 initializing... (Hot Reload Ready)');
|
||||||
|
|
||||||
this.core = new InsertrCore(options);
|
this.core = new InsertrCore(options);
|
||||||
this.auth = new InsertrAuth(options);
|
this.auth = new InsertrAuth(options);
|
||||||
this.editor = new InsertrEditor(this.core, this.auth, options);
|
this.editor = new InsertrEditor(this.core, this.auth, options);
|
||||||
|
|
||||||
// Auto-initialize if DOM is ready
|
// Auto-initialize if DOM is ready
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', () => this.start());
|
document.addEventListener('DOMContentLoaded', () => this.start());
|
||||||
} else {
|
} else {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Start the system - only creates the minimal trigger
|
// Start the system - only creates the minimal trigger
|
||||||
start() {
|
start() {
|
||||||
if (this.auth) {
|
if (this.auth) {
|
||||||
@@ -47,37 +47,36 @@ window.Insertr = {
|
|||||||
this.editor.start();
|
this.editor.start();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Public API methods
|
// Public API methods
|
||||||
login() {
|
login() {
|
||||||
return this.auth ? this.auth.toggleAuthentication() : null;
|
return this.auth ? this.auth.toggleAuthentication() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
if (this.auth && this.auth.isAuthenticated()) {
|
if (this.auth && this.auth.isAuthenticated()) {
|
||||||
this.auth.toggleAuthentication();
|
this.auth.toggleAuthentication();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleEditMode() {
|
toggleEditMode() {
|
||||||
return this.auth ? this.auth.toggleEditMode() : null;
|
return this.auth ? this.auth.toggleEditMode() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
isAuthenticated() {
|
isAuthenticated() {
|
||||||
return this.auth ? this.auth.isAuthenticated() : false;
|
return this.auth ? this.auth.isAuthenticated() : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
isEditMode() {
|
isEditMode() {
|
||||||
return this.auth ? this.auth.isEditMode() : false;
|
return this.auth ? this.auth.isEditMode() : false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Version info
|
// TODO: Version info based on package.json?
|
||||||
version: '1.0.0'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auto-initialize in development mode with proper DOM ready handling
|
// Auto-initialize in development mode with proper DOM ready handling
|
||||||
function autoInitialize() {
|
function autoInitialize() {
|
||||||
if (document.querySelector('[data-insertr-enhanced="true"]')) {
|
if (document.querySelector('.insertr')) {
|
||||||
window.Insertr.init();
|
window.Insertr.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,4 +89,4 @@ if (document.readyState === 'loading') {
|
|||||||
autoInitialize();
|
autoInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default window.Insertr;
|
export default window.Insertr;
|
||||||
|
|||||||
2403
package-lock.json
generated
2403
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "insertr",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "The Tailwind of CMS - Zero-configuration content editing for any static site",
|
|
||||||
"main": "lib/dist/insertr.js",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "node scripts/dev.js serve",
|
|
||||||
"dev:about": "live-server demo-site --port=3000 --open=/about.html",
|
|
||||||
"dev:check": "node scripts/dev.js check",
|
|
||||||
"dev:demo": "node scripts/dev.js demo",
|
|
||||||
"dev:help": "node scripts/dev.js help",
|
|
||||||
"build": "node scripts/build.js",
|
|
||||||
"test": "echo 'Test script placeholder - will add tests for insertr.js'",
|
|
||||||
"lint": "echo 'Linting placeholder - will add ESLint'",
|
|
||||||
"serve": "npm run dev",
|
|
||||||
"start": "npm run dev"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"cms",
|
|
||||||
"headless-cms",
|
|
||||||
"static-site-generator",
|
|
||||||
"content-management",
|
|
||||||
"build-time-enhancement",
|
|
||||||
"zero-config",
|
|
||||||
"go",
|
|
||||||
"javascript"
|
|
||||||
],
|
|
||||||
"author": "Your Name",
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/yourusername/insertr.git"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"live-server": "^1.2.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.0.0",
|
|
||||||
"npm": ">=8.0.0"
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"defaults",
|
|
||||||
"not IE 11"
|
|
||||||
],
|
|
||||||
"dependencies": {}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Test script to demonstrate Air hot reload functionality
|
|
||||||
# Shows how library changes automatically trigger CLI rebuild
|
|
||||||
|
|
||||||
echo "🧪 Testing Insertr Hot Reload Functionality"
|
|
||||||
echo "============================================"
|
|
||||||
|
|
||||||
cd insertr-cli
|
|
||||||
|
|
||||||
echo "1. Starting Air in background..."
|
|
||||||
air &
|
|
||||||
AIR_PID=$!
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
echo "2. Making a test change to the library..."
|
|
||||||
cd ../lib/src
|
|
||||||
# Make a test change
|
|
||||||
sed -i 's/Hot Reload Ready/Hot Reload TESTED/g' index.js
|
|
||||||
|
|
||||||
echo "3. Waiting for Air to detect change and rebuild..."
|
|
||||||
sleep 8
|
|
||||||
|
|
||||||
echo "4. Testing if the change was embedded in CLI..."
|
|
||||||
cd ../insertr-cli
|
|
||||||
if ./insertr enhance ../demo-site/ -o /tmp/test-output 2>/dev/null && grep -q "Hot Reload TESTED" /tmp/test-output/index.html; then
|
|
||||||
echo "✅ SUCCESS: Library change was automatically embedded in CLI!"
|
|
||||||
else
|
|
||||||
echo "❌ FAILED: Library change was not embedded"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "5. Reverting test change..."
|
|
||||||
cd ../lib/src
|
|
||||||
sed -i 's/Hot Reload TESTED/Hot Reload Ready/g' index.js
|
|
||||||
|
|
||||||
echo "6. Stopping Air..."
|
|
||||||
kill $AIR_PID 2>/dev/null
|
|
||||||
wait $AIR_PID 2>/dev/null
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🎉 Hot reload test completed!"
|
|
||||||
echo " Library changes automatically trigger:"
|
|
||||||
echo " • Library rebuild (npm run build)"
|
|
||||||
echo " • Asset copy to CLI"
|
|
||||||
echo " • CLI rebuild with embedded library"
|
|
||||||
echo " • Development server restart"
|
|
||||||
Reference in New Issue
Block a user