Skip to content
Draft
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
5 changes: 5 additions & 0 deletions import-bulk.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ <h2>Bulk Import</h2>
</div>
</div>
</div>
<div id="json">
<sp-checkbox class="option-field" id="import-local-json">
Save as JSON
</sp-checkbox>
</div>
<sp-checkbox class="option-field" id="import-local-da">
Save HTML for Document Authoring
</sp-checkbox>
Expand Down
5 changes: 5 additions & 0 deletions import.html
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ <h2>Workbench</h2>
</div>
</div>
</div>
<div id="json">
<sp-checkbox class="option-field" id="import-local-json">
Save as JSON
</sp-checkbox>
</div>
<sp-checkbox class="option-field" id="import-local-da">
Save HTML for Document Authoring
</sp-checkbox>
Expand Down
19 changes: 18 additions & 1 deletion importer-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,24 @@ Every new project has its own collection of new use cases which might be totally
- Linked images are not supported by Online Word thus they will be converted to image + link in Word.
- Reuse the DOM elements from the orignal page, no need to re-create complete DOM structures, especially if the Markdown is what you need. Example: Text in a `div` will become a paragraph, no need to create a `p` tag and replace the `div`. More generally, the DOM can be dirty, as long as the output Markdown looks as expected, it does not matter.
- If you import multiple page "types" for the project, you cannot either handle them in the same `import.js` file or have one `import-<type>.js` file per type (or any filename convention you lie). Use the UI options to point to a different import filename.


## JSON import

To import JSON, you need an `import.js` file with the following `transform` method:

```
export default {
transform: ({
document, url, html, params,
}) => {
return {
path: `/<path-to-file>.json`,
json: JSON.stringify(<object>, null, 2)
}
},
};
```

## Debugging

If you experience some deep nested Javascript exception, you can run the importer ui in developer mode, JS files will not be minified and obfuscated. Just run in the `/tools/importer/helix-importer-ui` folder:
Expand Down
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ <h2 slot="heading">Authoring Experience Selection</h2>
<sp-radio-group label="Choose an option" id="project-type-group" name="project-type-group">
<sp-radio value="doc">Document Authoring</sp-radio>
<sp-radio value="xwalk">AEM Authoring</sp-radio>
<sp-radio value="json">JSON</sp-radio>
</sp-radio-group>
<sp-button variant="primary" treatment="fill" slot="button" disabled>
Ok
Expand All @@ -123,6 +124,7 @@ <h2 slot="heading">Authoring Experience Selection</h2>
<sp-picker id="project-type" class="project-type" quiet size="s" label="Authoring Type">
<sp-menu-item value="doc">Document Authoring</sp-menu-item>
<sp-menu-item value="xwalk">AEM Authoring</sp-menu-item>
<sp-menu-item value="json">JSON</sp-menu-item>
<sp-divider></sp-divider>
<sp-menu-item value="reset">Reset</sp-menu-item>
</sp-picker>
Expand Down
12 changes: 10 additions & 2 deletions js/import/import.preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const PreviewElements = Object.freeze({
TRANSFORMED_HTML_TEXTAREA: document.getElementById('import-transformed-html'),
MD_SOURCE_TEXTAREA: document.getElementById('import-markdown-source'),
MD_PREVIEW_PANEL: document.getElementById('import-markdown-preview'),
// use md preview panel for json
JSON_PREVIEW_PANEL: document.getElementById('import-markdown-preview'),
IMPORT_FILE_PICKER_CONTAINER: document.getElementById('import-file-picker-container'),
JCR_PANEL: document.getElementById('import-jcr'),
});
Expand Down Expand Up @@ -153,7 +155,9 @@ const setupPreview = (parentSelector) => {
return preview;
};

const loadPreview = ({ md, html: outputHTML, jcr }) => {
const loadPreview = ({
md, html: outputHTML, jcr, json,
}) => {
if (outputHTML) {
preview.transformedEditor.setValue(html_beautify(outputHTML.replaceAll(/\s+/g, ' '), {
indent_size: '2',
Expand Down Expand Up @@ -181,7 +185,11 @@ const loadPreview = ({ md, html: outputHTML, jcr }) => {
});
} else {
preview.markdownEditor.setValue('No preview available.');
preview.markdownPreview.innerHTML = 'No preview available.';
if (json) {
preview.markdownPreview.innerHTML = `<pre><code>${json}</code></pre>`;
} else {
preview.markdownPreview.innerHTML = 'No preview available.';
}
}
};

Expand Down
10 changes: 7 additions & 3 deletions js/import/import.ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@
const postSuccessfulStep = async (results, originalURL) => {
let error = false;
await asyncForEach(results, async ({
docx, html, md, jcr, filename, path, report, from,
docx, html, md, jcr, json, filename, path, report, from,
}) => {
const data = {
url: originalURL,
path,
};

if (isSaveLocal && dirHandle && (docx || html || md || jcr)) {
if (isSaveLocal && dirHandle && (docx || html || md || jcr || json)) {
const files = [];
// if we were told to ave the doc file, add it to the list
if (config.fields['import-local-docx'] && docx) {
Expand Down Expand Up @@ -123,6 +123,10 @@
}
}

if (config.fields['import-local-json'] && json) {
files.push({ type: 'json', filename: path, data: json });
}

// if we were told to save the JCR package, add it to the list
if (config.fields['import-jcr-package'] && jcr) {
jcrPages.push({
Expand Down Expand Up @@ -385,7 +389,7 @@

disableProcessButtons();
toggleLoadingButton(IMPORT_BUTTON);
isSaveLocal = config.fields['import-local-docx'] || config.fields['import-local-html'] || config.fields['import-local-md'] || config.fields['import-jcr-package'] || config.fields['import-local-da'];
isSaveLocal = config.fields['import-local-docx'] || config.fields['import-local-html'] || config.fields['import-local-md'] || config.fields['import-jcr-package'] || config.fields['import-local-da'] || config.fields['import-local-json'];
if (isSaveLocal && !dirHandle) {
try {
dirHandle = await getDirectoryHandle();
Expand Down Expand Up @@ -453,7 +457,7 @@
const frame = getContentFrame();
const { originalURL } = frame.dataset;

console.error(`Error importing ${originalURL}.`, err);

Check warning on line 460 in js/import/import.ui.js

View workflow job for this annotation

GitHub Actions / Test

Unexpected console statement

if (!IS_BULK) {
alert.error('Error importing', err.message);
Expand Down
33 changes: 33 additions & 0 deletions js/shared/json-project.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/**
* @typedef {Object} JsonProjectConfig
* @property {string} origin - The base URL to fetch data from.
*/

/**
* Represents a JSON project.
*/
const JsonProject = () => {
/**
* Retrieves the type of the project.
* @returns "json" The type of the project ('json').
*/
const getType = () => 'json';

return {
getType,
};
};

export default JsonProject;
8 changes: 8 additions & 0 deletions js/shared/pollimporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,14 @@ export default class PollImporter {
this.running = false;
return;
}
} else if (projectType === 'json') {
const out = await WebImporter.html2json(
url,
documentClone,
this.projectTransform,
params,
);
results = Array.isArray(out) ? out : [out];
} else {
const out = await WebImporter.html2md(
url,
Expand Down
21 changes: 20 additions & 1 deletion js/shared/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@

import DocProject from './doc-project.js';
import XWalkProject from './xwalk-project.js';
import JsonProject from './json-project.js';
import { LOCAL_STORAGE_KEYS } from './localstorage.js';
/**
* @typedef {"doc" | "xwalk"} ProjectType
* @typedef {"doc" | "xwalk" | "json" } ProjectType
* @description Represents the possible types of a project.
*/

Expand All @@ -34,6 +35,7 @@ const Project = async (config) => {
const projectTypeMap = {
doc: DocProject,
xwalk: XWalkProject,
json: JsonProject,
};

/**
Expand Down Expand Up @@ -202,7 +204,10 @@ const Project = async (config) => {
const updateUI = () => {
const SAVE_AS_DOCX = document.getElementById('import-local-docx');
const DA_FIELD = document.getElementById('import-local-da');
const LOCAL_HTML = document.getElementById('import-local-html');
const LOCAL_MD = document.getElementById('import-local-md');
const XWALK_FIELDS = document.getElementById('xwalk');
const JSON_FIELDS = document.getElementById('json');
const JCR_ASSET_FOLDER = document.getElementById('jcr-asset-folder');
const JCR_SITE_FOLDER = document.getElementById('jcr-site-folder');

Expand Down Expand Up @@ -234,6 +239,7 @@ const Project = async (config) => {

if (projectType === 'doc') {
if (XWALK_FIELDS) XWALK_FIELDS.remove();
if (JSON_FIELDS) JSON_FIELDS.remove();

config.fields['import-jcr-package'] = false;

Expand All @@ -242,6 +248,19 @@ const Project = async (config) => {
if (jcrTab) {
jcrTab.remove();
}
} else if (projectType === 'json') {
if (XWALK_FIELDS) XWALK_FIELDS.remove();
if (SAVE_AS_DOCX) SAVE_AS_DOCX.remove();
if (DA_FIELD) DA_FIELD.remove();
if (LOCAL_HTML) LOCAL_HTML.remove();
if (LOCAL_MD) LOCAL_MD.remove();

config.fields['import-local-docx'] = false;
config.fields['import-local-json'] = true;
config.fields['import-jcr-package'] = false;
config.fields['import-local-da'] = false;
config.fields['import-local-html'] = false;
config.fields['import-local-md'] = false;
} else {
if (SAVE_AS_DOCX) SAVE_AS_DOCX.remove();
if (DA_FIELD) DA_FIELD.remove();
Expand Down
5 changes: 5 additions & 0 deletions modules/importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
html2md,
md2jcr,
rules,
html2json,
} from '@adobe/helix-importer';

import docxStylesXML from '../resources/styles.xml';
Expand Down Expand Up @@ -83,6 +84,9 @@ const options = {
async function html2mdWrapper(url, document, transformCfg, params) {
return html2md(url, document, transformCfg, options, params);
}
async function html2jsonWrapper(url, document, transformCfg, params) {
return html2json(url, document, transformCfg, options, params);
}

async function html2docxWrapper(url, document, transformCfg, params) {
return html2docx(url, document, transformCfg, options, params);
Expand All @@ -106,6 +110,7 @@ export {
FileUtils,
JCRUtils,
html2mdWrapper as html2md,
html2jsonWrapper as html2json,
html2docxWrapper as html2docx,
md2jcrWrapper as md2jcr,
rules,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"dependencies": {
"@adobe/helix-html-pipeline": "6.26.6",
"@adobe/helix-importer": "3.4.101",
"@adobe/helix-importer": "https://github.com/adobe/helix-importer/tree/json",
"@adobe/helix-importer-jcr-packaging": "2.0.10",
"@spectrum-web-components/bundle": "1.7.0",
"@spectrum-web-components/icons-workflow": "1.7.0",
Expand Down