mirror of
				https://github.com/XRPLF/xrpl-dev-portal.git
				synced 2025-11-04 11:55:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// @ts-check
 | 
						|
 | 
						|
import { getInnerText } from '@redocly/realm/dist/server/plugins/markdown/markdoc/helpers/get-inner-text.js';
 | 
						|
 | 
						|
import { dirname, relative, join as joinPath } from 'path';
 | 
						|
 | 
						|
export function codeSamples() {
 | 
						|
  /** @type {import("@redocly/realm/dist/server/plugins/types").PluginInstance } */
 | 
						|
  const instance = {
 | 
						|
    processContent: async (actions, { fs, cache }) => {
 | 
						|
      try {
 | 
						|
        const samples = [];
 | 
						|
        const allLands = new Set();
 | 
						|
        const allCodeSampleFiles = await fs.scan();
 | 
						|
 | 
						|
        const readmes = allCodeSampleFiles.filter((file) => file.relativePath.match(/^_code-samples[\/\\]([^\\\/]*)[\/\\]README\.md$/));
 | 
						|
 | 
						|
        for (const { relativePath } of readmes) {
 | 
						|
          const { data } = await cache.load(relativePath, 'markdown-ast');
 | 
						|
 | 
						|
          const dirPath = dirname(relativePath);
 | 
						|
          const langs = unique(
 | 
						|
            allCodeSampleFiles
 | 
						|
              .filter((file) => file.relativePath.startsWith(dirPath) && !file.relativePath.endsWith('README.md'))
 | 
						|
              .map((file) => relative(dirPath, file.relativePath).split('/')[0])
 | 
						|
          );
 | 
						|
          const title = extractFirstHeading(data.ast) || '';
 | 
						|
          samples.push({
 | 
						|
            path: dirPath,
 | 
						|
            title: title || toTitleCase(dirname(dirPath)),
 | 
						|
            description: getInnerText([data.ast.children[1]]).trim(),
 | 
						|
            href: joinPath('content', dirPath),
 | 
						|
            langs,
 | 
						|
          });
 | 
						|
 | 
						|
          langs.forEach((l) => allLands.add(l));
 | 
						|
        }
 | 
						|
 | 
						|
        const sortedSamples = samples.sort((a, b) => normalizeTitleForSort(a).localeCompare(normalizeTitleForSort(b)));
 | 
						|
 | 
						|
        actions.createSharedData('code-samples', {
 | 
						|
          codeSamples: sortedSamples,
 | 
						|
          langs: Array.from(allLands),
 | 
						|
        });
 | 
						|
        actions.addRouteSharedData('/resources/code-samples/', 'code-samples', 'code-samples');
 | 
						|
        actions.addRouteSharedData('/ja/resources/code-samples/', 'code-samples', 'code-samples');
 | 
						|
      } catch (e) {
 | 
						|
        console.log(e);
 | 
						|
      }
 | 
						|
    },
 | 
						|
  };
 | 
						|
  return instance;
 | 
						|
}
 | 
						|
 | 
						|
function normalizeTitleForSort(cs) {
 | 
						|
  if (cs.title.includes('Intro') || cs.title.includes('Quickstart')) {
 | 
						|
    return ` ${cs.title}`;
 | 
						|
  }
 | 
						|
  return cs.title;
 | 
						|
}
 | 
						|
 | 
						|
const WORDS_TO_CAPS = ['xrp'];
 | 
						|
 | 
						|
function toTitleCase(s) {
 | 
						|
  const words = s.split(/_|[^\w']/);
 | 
						|
  return words
 | 
						|
    .filter((word) => word)
 | 
						|
    .map((word) => (WORDS_TO_CAPS.includes(word) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)))
 | 
						|
    .join(' ')
 | 
						|
    .replace("'S", "'s")
 | 
						|
    .replace(' A ', ' a ');
 | 
						|
}
 | 
						|
 | 
						|
function unique(array) {
 | 
						|
  return Array.from(new Set(array));
 | 
						|
}
 | 
						|
 | 
						|
function extractFirstHeading(ast) {
 | 
						|
  let heading;
 | 
						|
 | 
						|
  visit(ast, (node) => {
 | 
						|
    if (!isNode(node)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (node.type === 'heading') {
 | 
						|
      heading = getInnerText([node]);
 | 
						|
      return EXIT;
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return heading;
 | 
						|
}
 | 
						|
 | 
						|
function isNode(value) {
 | 
						|
  return !!(value?.$$mdtype === 'Node');
 | 
						|
}
 | 
						|
 | 
						|
const EXIT = Symbol('Exit visitor');
 | 
						|
function visit(node, visitor) {
 | 
						|
  if (!node) return;
 | 
						|
 | 
						|
  const res = visitor(node);
 | 
						|
  if (res === EXIT) return res;
 | 
						|
 | 
						|
  for (const child of node.children) {
 | 
						|
    if (!child || typeof child === 'string') {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    const res = visit(child, visitor);
 | 
						|
    if (res === EXIT) return res;
 | 
						|
  }
 | 
						|
}
 |