Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions packages/model-viewer-effects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ npm install three @google/model-viewer @google/model-viewer-effects

```html
<!-- ES-Shims for older browser compatibility -->
<script async src="https://ga.jspm.io/npm:es-module-shims@1.7.1/dist/es-module-shims.js"></script>
<script async src="https://ga.jspm.io/npm:es-module-shims@2.6.2/dist/es-module-shims.js"></script>

<!-- Import Three.js using an import-map -->
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@^0.172.0/build/three.module.min.js"
"three": "https://cdn.jsdelivr.net/npm/three@^{{THREEJS_VERSION}}/build/three.module.min.js"
}
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion packages/model-viewer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import '@google/model-viewer';
It can also be used directly from various free CDNs such as [jsDelivr](https://www.jsdelivr.com/package/npm/@google/model-viewer) and Google's own [hosted libraries](https://developers.google.com/speed/libraries#model-viewer):

```html
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/{{MODELVIEWER_VERSION}}/model-viewer.min.js"></script>
```

For more detailed usage documentation and live examples, please visit our docs
Expand Down
2 changes: 1 addition & 1 deletion packages/modelviewer.dev/data/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
{
"name": "lottieLoaderLocation",
"htmlName": "lottieLoaderLocation",
"description": "This static, writable property sets <span class='attribute'>&lt;model-viewer&gt;</span>'s LottieLoader location URL. The default URL is <code>https://cdn.jsdelivr.net/npm/three@0.174.0/examples/jsm/loaders/LottieLoader.js</code>. It will also require the server to provide the lottie canvas module at <code>../libs/lottie_canvas.module.js</code>."
"description": "This static, writable property sets <span class='attribute'>&lt;model-viewer&gt;</span>'s LottieLoader location URL. The default URL is <code>https://cdn.jsdelivr.net/npm/three@{{THREEJS_VERSION}}/examples/jsm/loaders/LottieLoader.js</code>. It will also require the server to provide the lottie canvas module at <code>../libs/lottie_canvas.module.js</code>."
},
{
"name": "minimumRenderScale",
Expand Down
2 changes: 1 addition & 1 deletion packages/modelviewer.dev/data/faq.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
{
"name": "How should I access &lt;model-viewer&gt;?",
"htmlName": "cdn",
"description": "If you control your own hosting, the safest option is always to host model-viewer.min.js yourself on the same server as your site. For smaller sites and blogs, it is often more convenient to use one of various free CDNs - Google provides &lt;model-viewer&gt; as one of its hosted libraries, which we recommend as it is a fast and reliable CDN. Simply specify your desired version in the URL: <code>https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js</code>. We used to recommend unpkg, but it has had several serious outages recently. It can automatically pick the most recent version, but this is not a good practice as it slows loading (two requests) and ideally you should test when updating to ensure no bugs have been introduced. Another good option is jsDelivr.",
"description": "If you control your own hosting, the safest option is always to host model-viewer.min.js yourself on the same server as your site. For smaller sites and blogs, it is often more convenient to use one of various free CDNs - Google provides &lt;model-viewer&gt; as one of its hosted libraries, which we recommend as it is a fast and reliable CDN. Simply specify your desired version in the URL: <code>https://ajax.googleapis.com/ajax/libs/model-viewer/{{MODELVIEWER_VERSION}}/model-viewer.min.js</code>. We used to recommend unpkg, but it has had several serious outages recently. It can automatically pick the most recent version, but this is not a good practice as it slows loading (two requests) and ideally you should test when updating to ensure no bugs have been introduced. Another good option is jsDelivr.",
"links": [
"<a href='https://developers.google.com/speed/libraries#model-viewer'>Google Hosted Libraries</a>",
"<a href='https://www.jsdelivr.com/package/npm/@google/model-viewer'>jsDelivr</a>"
Expand Down
6 changes: 3 additions & 3 deletions packages/modelviewer.dev/examples/postprocessing/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@^0.172.0/build/three.module.min.js"
"three": "https://cdn.jsdelivr.net/npm/three@^{{THREEJS_VERSION}}/build/three.module.min.js"
}
}
</script>
Expand Down Expand Up @@ -114,7 +114,7 @@ <h2 class="demo-title">Setup Post Processing</h2>
<script type="importmap-noexecute">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@^0.172.0/build/three.module.min.js"
"three": "https://cdn.jsdelivr.net/npm/three@^{{THREEJS_VERSION}}/build/three.module.min.js"
}
}
</script>
Expand Down Expand Up @@ -459,7 +459,7 @@ <h2 class="demo-title">Custom Effects</h2>
</div>
</model-viewer>
<script type="module">
import * as PostProcessing from 'https://cdn.jsdelivr.net/npm/postprocessing@6.35.3/build/index.js';
import * as PostProcessing from 'https://cdn.jsdelivr.net/npm/postprocessing@{{POSTPROCESSING_VERSION}}/build/index.js';
const customComposer = document.querySelector("effect-composer#customComposer");

const grid = new PostProcessing.GridEffect();
Expand Down
2 changes: 1 addition & 1 deletion packages/modelviewer.dev/examples/twitter/player.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<meta name="color-scheme" content="dark light">

<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/{{MODELVIEWER_VERSION}}/model-viewer.min.js"></script>
<script defer src="https://web3dsurvey.com/collector.js"></script>
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
Expand Down
2 changes: 1 addition & 1 deletion packages/modelviewer.dev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ <h3 class="grouping-title grouping-title-new quick-start">Quick Start</h3>
<example-snippet inert-script stamp-to="demo-container" highlight-as="html">
<template>
<!-- Import the component -->
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/{{MODELVIEWER_VERSION}}/model-viewer.min.js"></script>

<!-- Use it like any other HTML element -->
<model-viewer alt="Neil Armstrong's Spacesuit from the Smithsonian Digitization Programs Office and National Air and Space Museum" src="shared-assets/models/NeilArmstrong.glb" ar environment-image="shared-assets/environments/moon_1k.hdr" poster="shared-assets/models/NeilArmstrong.webp" shadow-intensity="1" camera-controls touch-action="pan-y"></model-viewer>
Expand Down
2 changes: 2 additions & 0 deletions packages/modelviewer.dev/scripts/ci-before-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ done
# Add a "VERSION" file containing the last git commit message
git log -n 1 > $DEPLOY_ROOT/VERSION

node scripts/update-versions.js

git status --ignored

popd
Expand Down
208 changes: 208 additions & 0 deletions packages/modelviewer.dev/scripts/update-versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/usr/bin/env node

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import chalk from 'chalk';

// ESM module resolution
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// ============================================================
// CONFIGURATION
// ============================================================

const CONFIG = {
packagePaths: {
modelViewer: path.resolve(__dirname, '../../model-viewer/package.json'),
effects: path.resolve(__dirname, '../../model-viewer-effects/package.json'),
},
targetFiles: [
'../dist/index.html',
'../dist/data/faq.json',
'../dist/data/docs.json',
'../dist/examples/postprocessing/index.html',
'../dist/examples/twitter/player.html',
].map(file => path.resolve(__dirname, file)),
placeholders: {
modelViewer: '{{MODELVIEWER_VERSION}}',
three: '{{THREEJS_VERSION}}',
postprocessing: '{{POSTPROCESSING_VERSION}}',
},
};

// ============================================================
// LOGGER UTILITIES
// ============================================================

const logger = {
success: (msg) => console.log(chalk.green(`✓ ${msg}`)),
error: (msg) => console.log(chalk.red(`✗ ${msg}`)),
warning: (msg) => console.log(chalk.yellow(`⚠ ${msg}`)),
info: (msg) => console.log(chalk.blue(`ℹ ${msg}`)),
separator: () => console.log(''),
};

// ============================================================
// FILE OPERATIONS
// ============================================================

/**
* Reads and parses a JSON file safely
* @param {string} filePath - Path to JSON file
* @returns {Object|null} Parsed JSON or null on error
*/
const readJsonFile = (filePath) => {
try {
if (!fs.existsSync(filePath)) {
throw new Error(`File not found: ${filePath}`);
}
const content = fs.readFileSync(filePath, 'utf8');
return JSON.parse(content);
} catch (error) {
logger.error(`Error reading ${filePath}: ${error.message}`);
return null;
}
};

/**
* Replaces placeholders in a file with actual values
* @param {string} filePath - Target file path
* @param {Object} replacements - Key-value pairs for replacement
* @returns {boolean} Success status
*/
const replacePlaceholdersInFile = (filePath, replacements) => {
if (!fs.existsSync(filePath)) {
logger.warning(`File ${filePath} does not exist - skipped`);
return false;
}

try {
let content = fs.readFileSync(filePath, 'utf8');
let hasChanges = false;

for (const [placeholder, value] of Object.entries(replacements)) {
if (content.includes(placeholder)) {
content = content.replaceAll(placeholder, value);
hasChanges = true;
} else {
logger.warning(`Placeholder ${placeholder} not found in ${path.basename(filePath)}`);
}
}

if (hasChanges) {
fs.writeFileSync(filePath, content, 'utf8');
logger.success(`Updated: ${path.basename(filePath)}`);
return true;
}

return false;
} catch (error) {
logger.error(`Error processing ${filePath}: ${error.message}`);
return false;
}
};

// ============================================================
// VERSION EXTRACTION
// ============================================================

/**
* Extracts package version from package.json
* @param {Object} packageJson - Parsed package.json
* @param {string} packageName - Name of the package
* @returns {string} Cleaned version string
*/
const extractPackageVersion = (packageJson, packageName) => {
const version =
packageJson.dependencies?.[packageName] ||
packageJson.devDependencies?.[packageName] ||
'';

return version.replace(/^[^\d]*/, ''); // Remove leading symbols (^, ~, etc.)
};

/**
* Collects all required versions from package.json files
* @returns {Object|null} Version object or null on error
*/
const collectVersions = () => {
const modelViewerPkg = readJsonFile(CONFIG.packagePaths.modelViewer);
const effectsPkg = readJsonFile(CONFIG.packagePaths.effects);

if (!modelViewerPkg || !effectsPkg) {
return null;
}

const versions = {
three: extractPackageVersion(modelViewerPkg, 'three'),
modelViewer: modelViewerPkg.version || '',
postprocessing: extractPackageVersion(effectsPkg, 'postprocessing'),
};

// Validate all versions are present
const missingVersions = Object.entries(versions)
.filter(([_, version]) => !version)
.map(([key]) => key);

if (missingVersions.length > 0) {
logger.error(`Missing versions: ${missingVersions.join(', ')}`);
return null;
}

return versions;
};

// ============================================================
// MAIN EXECUTION
// ============================================================

/**
* Main execution function
*/
const main = () => {
logger.info('Starting version replacement...');
logger.separator();

// Collect versions
const versions = collectVersions();
if (!versions) {
process.exit(1);
}

// Display versions
logger.info(`three.js: ${versions.three}`);
logger.info(`model-viewer: ${versions.modelViewer}`);
logger.info(`postprocessing: ${versions.postprocessing}`);
logger.separator();

// Prepare replacements
const replacements = {
[CONFIG.placeholders.three]: versions.three,
[CONFIG.placeholders.modelViewer]: versions.modelViewer,
[CONFIG.placeholders.postprocessing]: versions.postprocessing,
};

// Process all target files
const results = CONFIG.targetFiles.map(file =>
replacePlaceholdersInFile(file, replacements)
);

const successCount = results.filter(Boolean).length;
const totalCount = CONFIG.targetFiles.length;

// Final summary
logger.separator();
if (successCount === totalCount) {
logger.success(`All ${totalCount} files updated successfully!`);
} else if (successCount > 0) {
logger.warning(`${successCount} out of ${totalCount} files updated`);
} else {
logger.error('No files were updated!');
process.exit(1);
}
};

// Execute
main();
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const modelViewerTemplate = `<!doctype html>
<!-- <model-viewer> HTML element -->
REPLACEME
<!-- Loads <model-viewer> for browsers: -->
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/{{MODELVIEWER_VERSION}}/model-viewer.min.js"></script>
</body>
</html>`;

Expand Down