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
48 changes: 29 additions & 19 deletions scripts/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ function capitalize(s) {
}

function normalizeName(name) {
return name
.split("_")
.map((name) => capitalize(name))
.join(" ");
return name.split("_").map(capitalize).join(" ");
}

export function renderMarkdown(solution, file) {
Expand All @@ -19,6 +16,9 @@ export function renderMarkdown(solution, file) {
// Convert Markdown to HTML
const htmlContent = marked(content);

const solutionId = basename(solution, extname(solution));
const fileId = basename(file, extname(file));

// Wrap the HTML content with the necessary HTML and CSS
const htmlTemplate = `
<!DOCTYPE html>
Expand All @@ -27,9 +27,8 @@ export function renderMarkdown(solution, file) {
<meta charset="utf-8">
<link rel="icon" type="image/svg+xml" sizes="any" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TigerGraph - ${normalizeName(
basename(solution, extname(solution))
)} - ${normalizeName(basename(file, extname(file)))} </title>
<title>TigerGraph - ${normalizeName(solutionId)} - ${normalizeName(fileId)}</title>

<script>
(function () {
try {
Expand All @@ -56,29 +55,37 @@ export function renderMarkdown(solution, file) {
} catch (e) {}
})();
</script>

<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
background-color: transparent;
}
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;

padding: 45px;

background-color: transparent;
}

@media (max-width: 767px) {
.markdown-body {
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
</style>
}
</style>

<script>
// check to hide instructions section
document.addEventListener('DOMContentLoaded', function () {
try {
var params = new URLSearchParams(window.location.search);
var shouldHide = /^(1|true|yes)$/i.test((params.get('hideInstructions') || '').trim());
if (!shouldHide) return;

var container = document.querySelector('article.markdown-body');
if (!container) return;

var h1s = container.querySelectorAll('h1');
var target = null;
for (var i = 0; i < h1s.length; i++) {
Expand All @@ -92,6 +99,7 @@ export function renderMarkdown(solution, file) {
el = el.nextElementSibling;
}
}

// Special handling for transaction_fraud: hide the entire "Installation Note for Queries" section
var solutionId = (document.body && document.body.getAttribute('data-solution-id')) || '';
if (solutionId === 'transaction_fraud') {
Expand All @@ -114,7 +122,9 @@ export function renderMarkdown(solution, file) {
});
</script>
</head>
<body data-solution-id="${basename(solution, extname(solution))}">

<!-- ADDED (from dev): used by the hide logic above -->
<body data-solution-id="${solutionId}">
<article class="markdown-body">
${htmlContent}
</article>
Expand Down
109 changes: 33 additions & 76 deletions scripts/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async function syncFolder(folder, cacheControl = disableCacheControl) {
Prefix: folder,
})
.promise();
const conents = result.Contents;
const conents = result.Contents || [];

// delete all remote file not existed on local
for (let content of conents) {
Expand Down Expand Up @@ -119,7 +119,7 @@ function getAllSolutions() {
return metaFiles.map((file) => file.slice(0, -"/meta/meta.yml".length));
}

// Find a case-insensitive Readme.md file in the solution root

function findReadmeFile(solutionDir) {
try {
const files = fs.readdirSync(solutionDir);
Expand Down Expand Up @@ -163,16 +163,14 @@ async function getSolution(dir) {
await syncFolder(`${dir}/model`);
await syncFolder(`${dir}/doc`);

const insightsFiles = await globSync(`${dir}/meta/Insights*.json`);
const insightsFiles = globSync(`${dir}/meta/Insights*.json`);
content.metadata.hasInsights = insightsFiles.length > 0;

const markdownFiles = globSync([
`${dir}/model/**/*.md`,
`${dir}/doc/**/*.md`,
]);
const markdownFiles = globSync([`${dir}/model/**/*.md`, `${dir}/doc/**/*.md`]);
const htmlFiles = [];
for (let markdownFile of markdownFiles) {
const html = renderMarkdown(dir, markdownFile);

const htmlFile = path.join(
path.dirname(markdownFile),
path.basename(markdownFile, path.extname(markdownFile)) + ".html"
Expand All @@ -196,7 +194,7 @@ async function getSolution(dir) {
}
}

// Handle root-level README (case-insensitive)

const readmeFile = findReadmeFile(dir);
if (readmeFile) {
const html = renderMarkdown(dir, readmeFile);
Expand All @@ -216,7 +214,6 @@ async function getSolution(dir) {
try {
const data = await s3.upload(params).promise();
console.log(`${htmlFile} => ${data.Location}`);
// Expose README link separately
content.metadata.readme = data.Location;
} catch (error) {
console.error("Error uploading html file:", error);
Expand Down Expand Up @@ -256,9 +253,7 @@ function concatFilesForQuery(files, lastFiles, graphName, is_library) {
content += `INSTALL QUERY ALL\n`;
}

const lastFileContents = lastFiles.map((file) =>
fs.readFileSync(file, "utf8")
);
const lastFileContents = lastFiles.map((file) => fs.readFileSync(file, "utf8"));
for (let i = 0; i < lastFiles.length; i++) {
content += "#File: " + lastFiles[i] + "\n";
content += lastFileContents[i];
Expand All @@ -278,9 +273,7 @@ function concatFilesForLastFile(lastFiles, graphName, is_library) {
}

let content = `USE GRAPH ${graphName}\n`;
const lastFileContents = lastFiles.map((file) =>
fs.readFileSync(file, "utf8")
);
const lastFileContents = lastFiles.map((file) => fs.readFileSync(file, "utf8"));
for (let i = 0; i < lastFiles.length; i++) {
content += lastFileContents[i];
content += "\n";
Expand All @@ -294,9 +287,7 @@ function concatFilesForLastFile(lastFiles, graphName, is_library) {
function concatLoadingFiles(files) {
const fileContents = files
.map((file) => fs.readFileSync(file, "utf8"))
.map((content) =>
content.replaceAll("tigergraph-solution-kits", getBucketName())
);
.map((content) => content.replaceAll("tigergraph-solution-kits", getBucketName()));

let content = "";
for (let i = 0; i < files.length; i++) {
Expand All @@ -321,28 +312,25 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) {
styleJSON = fs.readFileSync(`${dir}/meta/style.json`, "utf8");
} catch (error) {}

const queryFiles = globSync([
`${dir}/queries/*.gsql`,
`${dir}/queries/*/*.gsql`,
]);
const queryFiles = globSync([`${dir}/queries/*.gsql`, `${dir}/queries/*/*.gsql`]);

const firstFiles = [];
for (let file of first) {
const path = `${dir}/queries/${file}`;
if (queryFiles.includes(path)) {
firstFiles.push(path);
const p = `${dir}/queries/${file}`;
if (queryFiles.includes(p)) {
firstFiles.push(p);
}
}
const lastFiles = [];
for (let file of last) {
const path = `${dir}/queries/${file}`;
if (queryFiles.includes(path)) {
lastFiles.push(path);
const p = `${dir}/queries/${file}`;
if (queryFiles.includes(p)) {
lastFiles.push(p);
}
}

const middleFiles = queryFiles.filter(
(file) => !firstFiles.includes(file) && !lastFiles.includes(file)
(f) => !firstFiles.includes(f) && !lastFiles.includes(f)
);

const query = concatFilesForQuery(
Expand All @@ -360,7 +348,7 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) {
const resetFiles = globSync(`${dir}/reset/*.gsql`);
const reset = concatFiles(resetFiles);

const insightsFiles = await globSync(`${dir}/meta/Insights*.json`);
const insightsFiles = globSync(`${dir}/meta/Insights*.json`);
const insightsApplications = [];
for (let insightsFile of insightsFiles) {
const application = JSON.parse(fs.readFileSync(`${insightsFile}`, "utf8"));
Expand All @@ -383,17 +371,15 @@ async function main() {
const solutions = getAllSolutions();
const metadataList = [];
for (let solution of solutions) {
const { metadata, queries: { first, last } = {} } = await getSolution(
solution
);
const { metadata, queries: { first, last } = {} } = await getSolution(solution);

if (metadata.production === false) {
console.log("hide solution", metadata.name);
continue;
}

metadataList.push({
...metadata,
...metadata, // includes metadata.images, metadata.docLinks, and ADDED metadata.readme when present
path: solution,
});

Expand All @@ -404,6 +390,7 @@ async function main() {
metadata.graph,
metadata.is_library
);

const params = {
...commonBucketConfig,
Key: `${solution}/meta.json`,
Expand Down Expand Up @@ -460,28 +447,16 @@ async function main() {

main();

// Debug code
// function decodeSolution(path) {
// const file = fs.readFileSync(path, "utf8");
// const content = JSON.parse(file);
// const { schema, query, sampleLoadingJob, reset } = content;
// console.log(schema);
// console.log(query);
// console.log(sampleLoadingJob);
// console.log(reset);
// }

async function generateFileForImportSolution() {
const dir = "solution_metadata";
const list_data = [];
fs.mkdirSync(dir);
// (small safety: allow reruns without throwing)
fs.mkdirSync(dir, { recursive: true });

const solutions = getAllSolutions();
const metadataList = [];
for (let solution of solutions) {
const { metadata, queries: { first, last } = {} } = await getSolution(
solution
);
const { metadata, queries: { first, last } = {} } = await getSolution(solution);

if (metadata.production === false) {
console.log("hide solution", metadata.name);
Expand All @@ -498,8 +473,7 @@ async function generateFileForImportSolution() {

// strip aws s3 url prefix
if (metadata.icon) {
metadata.icon =
dir + "/" + metadata.icon.slice(metadata.icon.indexOf(solution));
metadata.icon = dir + "/" + metadata.icon.slice(metadata.icon.indexOf(solution));
}
if (metadata.images) {
metadata.images = metadata.images.map((image) => {
Expand All @@ -513,8 +487,8 @@ async function generateFileForImportSolution() {
initQuery: solutionDetails.lastQuery,
});

if (!solutionDetails.is_library) {
// https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/financial_crime/application_fraud/4.x/solution_with_data.tar.gz

if (!metadata.is_library) {
const solution_with_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_with_data.tar.gz`;
const solution_without_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_without_data.tar.gz`;
list_data.push({
Expand All @@ -529,23 +503,14 @@ async function generateFileForImportSolution() {
// copy images and icon
fs.mkdirSync(`${dir}/${solution}/meta`, { recursive: true });
if (fs.existsSync(`${solution}/meta/icon.png`)) {
fs.copyFileSync(
`${solution}/meta/icon.png`,
`${dir}/${solution}/meta/icon.png`
);
fs.copyFileSync(`${solution}/meta/icon.png`, `${dir}/${solution}/meta/icon.png`);
} else if (fs.existsSync(`${solution}/meta/icon.jpg`)) {
fs.copyFileSync(
`${solution}/meta/icon.jpg`,
`${dir}/${solution}/meta/icon.jpg`
);
fs.copyFileSync(`${solution}/meta/icon.jpg`, `${dir}/${solution}/meta/icon.jpg`);
} else if (fs.existsSync(`${solution}/meta/icon.svg`)) {
fs.copyFileSync(
`${solution}/meta/icon.svg`,
`${dir}/${solution}/meta/icon.svg`
);
fs.copyFileSync(`${solution}/meta/icon.svg`, `${dir}/${solution}/meta/icon.svg`);
}
if (fs.existsSync(`${solution}/meta/images`)) {
fs.mkdirSync(`${dir}/${solution}/meta/images`);
fs.mkdirSync(`${dir}/${solution}/meta/images`, { recursive: true });
const images = globSync([`${solution}/meta/images/*`]);
for (let image of images) {
const fileName = path.basename(image);
Expand All @@ -554,15 +519,7 @@ async function generateFileForImportSolution() {
}
}

fs.writeFileSync(
`${dir}/solution_list.json`,
JSON.stringify(metadataList, null, 2)
);
fs.writeFileSync(
`${dir}/solution_data.json`,
JSON.stringify(list_data, null, 2)
);
fs.writeFileSync(`${dir}/solution_list.json`, JSON.stringify(metadataList, null, 2));
fs.writeFileSync(`${dir}/solution_data.json`, JSON.stringify(list_data, null, 2));
}

// generate meta data for import solution, used by https://dl.tigergraph.com/?tab=solution
// generateFileForImportSolution();