Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c27a763
Initial plan
Copilot Oct 30, 2025
265bc9b
Initial exploration - repository state analyzed
Copilot Oct 30, 2025
839db39
Add ECS core infrastructure with plugins and systems
Copilot Oct 30, 2025
3d71c45
Remove dist directory from git tracking
Copilot Oct 30, 2025
5c7cb02
Add plugin documentation and index
Copilot Oct 30, 2025
316eafa
Address code review feedback - clarify plugin import paths
Copilot Oct 30, 2025
d876c1a
Add comprehensive implementation summary
Copilot Oct 30, 2025
34d4978
Update package.json with new content
kalwalt Oct 30, 2025
bf64747
Create vite.config.js file
kalwalt Oct 30, 2025
fe301d0
Updating README.md with new ECS architecture and plugin system details.
kalwalt Oct 30, 2025
2d9e124
Update package.json
kalwalt Oct 30, 2025
5525b35
formatting code with prettier
kalwalt Oct 30, 2025
33c9e95
new image-example for testing
kalwalt Oct 30, 2025
11fb9f4
docs: link Image Example in Running Examples
kalwalt Oct 30, 2025
00eeaff
docs: enhance README formatting for clarity on Webpack, Vite, and Exa…
kalwalt Oct 30, 2025
930de57
Fix webpack output filename to match package.json main field
Copilot Oct 30, 2025
942abb4
Update webpack config: filename to arjs-core.js and library to ARJSCore
Copilot Oct 30, 2025
3736ad4
feat: add ECS architecture with Vitest configuration and tests
kalwalt Oct 30, 2025
41ac1f6
Merge remote-tracking branch 'origin/copilot/add-ecs-architecture-and…
kalwalt Oct 30, 2025
61356e7
chore: remove jsdom dependency and update Vitest config to use node e…
kalwalt Oct 30, 2025
4b5077f
test: add unit tests for PluginManager and smoke tests for plugins
kalwalt Oct 30, 2025
a6843e7
ci: add CI workflow for automated testing and builds
kalwalt Oct 30, 2025
82af9d3
fix for formatting issue
kalwalt Oct 30, 2025
c8ef462
ci: update CI workflow to use webpack for stable builds and add Vite …
kalwalt Oct 30, 2025
9b53573
chore: add Rollup as a dev dependency and include optional Rollup pac…
kalwalt Oct 30, 2025
4e9b786
formatting code
kalwalt Oct 30, 2025
3fb84be
chore: update .gitignore and package.json for coverage and dependency…
kalwalt Oct 30, 2025
1cbfba2
Create examples/index.html with AR.js-core examples
kalwalt Oct 30, 2025
d9bf898
feat: add initial HTML structure and Vite configuration for AR.js-cor…
kalwalt Oct 30, 2025
0b3fb67
feat: enhance HTML structure and update README for AR.js Core plugins
kalwalt Oct 30, 2025
2d24215
Merge remote-tracking branch 'origin/copilot/add-ecs-architecture-and…
kalwalt Oct 30, 2025
b6517aa
feat: enhance index.html layout and update package.json for versionin…
kalwalt Oct 30, 2025
72ef4bd
Initial plan
Copilot Oct 30, 2025
1d92b2c
feat(profile): add QUALITY_TIERS and auto device profile; docs: migra…
kalwalt Oct 30, 2025
c7ed476
Implement capability-based device profiling with backward compatibility
Copilot Oct 30, 2025
1be9af2
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt Oct 30, 2025
6ecf098
Optimize micro-benchmark and remove dead code per code review
Copilot Oct 30, 2025
47c1656
feat(profile): implement capability-based device profiling with backw…
kalwalt Oct 30, 2025
7e0ee68
feat(profile): enhance mobile device detection with additional patterns
Copilot Oct 30, 2025
2a467d2
feat(profile): capability-based auto profile; keep legacy mappings
kalwalt Oct 30, 2025
e42bb56
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt Oct 30, 2025
2d7c53e
feat(profile): capability-based auto profile; keep legacy mappings
kalwalt Oct 30, 2025
7f39264
docs(plugins): add migration note for capability-based device profiles
kalwalt Oct 30, 2025
27285ca
refactor(default-policy): improve code readability with consistent fo…
kalwalt Oct 30, 2025
468a221
chore(gitattributes): add line ending normalization for JavaScript an…
kalwalt Oct 30, 2025
5b3143e
refactor: standardize quote style across JavaScript files and update …
kalwalt Oct 30, 2025
74728e0
chore(ci): update Node.js version to 22.x for CI stability
kalwalt Oct 30, 2025
a4541d8
chore(ci): update Node.js version to 22.x for CI stability
kalwalt Oct 30, 2025
b092da9
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt Oct 31, 2025
420fec4
docs: add newline at end of README.md for consistency
kalwalt Oct 31, 2025
6ba45e7
Merge pull request #5 from AR-js-org/copilot/replace-static-device-pr…
kalwalt Oct 31, 2025
437900f
feat(engine): add static VERSION/REVISION from package.json; test: ad…
kalwalt Oct 31, 2025
3279191
fix(engine): add newline at end of file for consistency
kalwalt Oct 31, 2025
51cc5a2
feat(engine): add tests for VERSION and REVISION from package.json
kalwalt Oct 31, 2025
d5e767a
Add ESLint, Husky, lint-staged and CI workflow for format/lint enforc…
Copilot Oct 31, 2025
5df0635
Update Husky pre-commit hook to use v10-compatible format
Copilot Oct 31, 2025
2ba3aca
Add ESLint cache and improve lint-staged performance
Copilot Oct 31, 2025
abab221
Add explicit permissions to CI workflow for security
Copilot Oct 31, 2025
6eff7fe
Update .nvmrc with Node.js version v22.21.1
kalwalt Oct 31, 2025
ab41c8a
Update CI workflow to run on all branches and use ubuntu-24.04
Copilot Oct 31, 2025
4066cb7
chore(ci): update format-lint workflow to use .nvmrc for Node.js version
kalwalt Oct 31, 2025
c0d8888
feat(ci): enhance CI workflow with formatting and linting checks
kalwalt Oct 31, 2025
eea9464
AR.js Core ECS + ArtoolkitPlugin example (#7)
kalwalt Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ npm run serve:vite
```

**Examples:**

- Minimal Example: examples/minimal/index.html (Vite: http://localhost:5173/examples/minimal/index.html)
- Image Source Example: examples/basic-ecs/image-example.html (Vite: http://localhost:5173/examples/basic-ecs/image-example.html)

Expand All @@ -94,4 +95,4 @@ The original Source and Profile classes are still available and fully supported:
import { Source, Profile } from "ar.js-core";
```

See existing documentation for legacy API usage.
See existing documentation for legacy API usage.
263 changes: 134 additions & 129 deletions examples/basic-ecs/image-example.html
Original file line number Diff line number Diff line change
@@ -1,167 +1,172 @@
<!doctype html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
<title>AR.js-core ECS - Image Source Example</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
background: #111;
color: #eee;
font-family: system-ui, sans-serif;
}
#app {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
#panel {
position: absolute;
top: 12px;
left: 12px;
right: 12px;
max-width: 720px;
padding: 10px 12px;
background: rgba(0,0,0,0.55);
border-radius: 6px;
z-index: 10;
}
#row {
display: flex;
gap: 8px;
margin-top: 8px;
}
#url {
flex: 1;
min-width: 240px;
color: #eee;
background: rgba(255,255,255,0.08);
border: 1px solid rgba(255,255,255,0.2);
padding: 6px 8px;
border-radius: 4px;
outline: none;
}
button {
color: #111;
background: #9ef01a;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* The image element created by the plugin gets id=arjs-video */
#arjs-video {
position: absolute !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
object-fit: contain;
z-index: -2 !important;
}
.status-ok { color: #9ef01a; }
.status-bad { color: #ff6b6b; }
html,
body {
margin: 0;
padding: 0;
height: 100%;
background: #111;
color: #eee;
font-family: system-ui, sans-serif;
}
#app {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
#panel {
position: absolute;
top: 12px;
left: 12px;
right: 12px;
max-width: 720px;
padding: 10px 12px;
background: rgba(0, 0, 0, 0.55);
border-radius: 6px;
z-index: 10;
}
#row {
display: flex;
gap: 8px;
margin-top: 8px;
}
#url {
flex: 1;
min-width: 240px;
color: #eee;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 6px 8px;
border-radius: 4px;
outline: none;
}
button {
color: #111;
background: #9ef01a;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* The image element created by the plugin gets id=arjs-video */
#arjs-video {
position: absolute !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
object-fit: contain;
z-index: -2 !important;
}
.status-ok {
color: #9ef01a;
}
.status-bad {
color: #ff6b6b;
}
</style>
</head>
<body>
<div id="app">
<div id="panel">
</head>
<body>
<div id="app">
<div id="panel">
<div><strong>AR.js-core ECS Image Example</strong></div>
<div id="status" class="status-ok">Ready</div>
<div id="row">
<input
id="url"
type="text"
placeholder="Enter image URL..."
value="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Example.jpg/640px-Example.jpg"
/>
<button id="load">Load</button>
<button id="clear">Clear</button>
<input
id="url"
type="text"
placeholder="Enter image URL..."
value="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Example.jpg/640px-Example.jpg"
/>
<button id="load">Load</button>
<button id="clear">Clear</button>
</div>
</div>
</div>
</div>

<script type="module">
import { Engine } from "../../src/core/engine.js";
import { imagePlugin } from "../../plugins/source/image.js";
<script type="module">
import { Engine } from "../../src/core/engine.js";
import { imagePlugin } from "../../plugins/source/image.js";

const statusEl = document.getElementById("status");
const urlEl = document.getElementById("url");
const loadBtn = document.getElementById("load");
const clearBtn = document.getElementById("clear");
const statusEl = document.getElementById("status");
const urlEl = document.getElementById("url");
const loadBtn = document.getElementById("load");
const clearBtn = document.getElementById("clear");

// Initialize engine (provides eventBus and context)
const engine = new Engine();
const context = engine.getContext();
// Initialize engine (provides eventBus and context)
const engine = new Engine();
const context = engine.getContext();

// Initialize the image plugin
await imagePlugin.init(context);
// Initialize the image plugin
await imagePlugin.init(context);

function setStatus(msg, ok = true) {
function setStatus(msg, ok = true) {
statusEl.textContent = msg;
statusEl.className = ok ? "status-ok" : "status-bad";
}
}

function removeExisting() {
function removeExisting() {
const el = document.getElementById("arjs-video");
if (el && el.parentNode) el.parentNode.removeChild(el);
}
}

async function loadImage(url) {
async function loadImage(url) {
if (!url) return;
try {
setStatus("Loading image...", true);
// Remove any previous image first
removeExisting();
setStatus("Loading image...", true);
// Remove any previous image first
removeExisting();

// Ask plugin to capture; it will append to document.body on load
const frame = await imagePlugin.capture(
{
sourceUrl: url,
sourceWidth: 640,
sourceHeight: 480,
displayWidth: 640,
displayHeight: 480,
},
context
);
// Ask plugin to capture; it will append to document.body on load
const frame = await imagePlugin.capture(
{
sourceUrl: url,
sourceWidth: 640,
sourceHeight: 480,
displayWidth: 640,
displayHeight: 480,
},
context,
);

// If not yet appended by plugin, ensure it’s visible
if (frame?.element && !frame.element.isConnected) {
document.body.appendChild(frame.element);
}
// If not yet appended by plugin, ensure it’s visible
if (frame?.element && !frame.element.isConnected) {
document.body.appendChild(frame.element);
}

setStatus("Image loaded", true);
setStatus("Image loaded", true);
} catch (e) {
console.error(e);
setStatus("Failed to load image. Check the URL and CORS.", false);
console.error(e);
setStatus("Failed to load image. Check the URL and CORS.", false);
}
}
}

// Wire up UI
loadBtn.addEventListener("click", () => {
// Wire up UI
loadBtn.addEventListener("click", () => {
const url = (urlEl.value || "").trim();
loadImage(url);
});
});

clearBtn.addEventListener("click", () => {
clearBtn.addEventListener("click", () => {
removeExisting();
setStatus("Cleared", true);
});
});

// Auto-load the initial URL
loadImage(urlEl.value);
</script>
</body>
</html>
// Auto-load the initial URL
loadImage(urlEl.value);
</script>
</body>
</html>
4 changes: 2 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "ARjs-core.js",
library: "ARjs-core",
filename: "ar-core.js",
library: "ar.js-core",
libraryTarget: "umd",
// @see: https://github.com/webpack/webpack/issues/3929
libraryExport: "default",
Expand Down