mirror of
				https://github.com/ikatyang/emoji-cheat-sheet.git
				synced 2025-05-29 01:49:25 +08:00 
			
		
		
		
	refactor: rewrite with typescript
This commit is contained in:
		
							parent
							
								
									277d9e143e
								
							
						
					
					
						commit
						e33fa33e1e
					
				@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "emoji-cheat-sheet-generator",
 | 
			
		||||
  "name": "emoji-cheat-sheet",
 | 
			
		||||
  "version": "0.0.0-dev",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "author": "ikatyang",
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
  "homepage": "https://github.com/ikatyang/emoji-cheat-sheet",
 | 
			
		||||
  "repository": "https://github.com/ikatyang/emoji-cheat-sheet/tree/generator",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "lint": "tslint -p ./tsconfig.json",
 | 
			
		||||
    "generate": "node ./scripts/generate.js"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
@ -16,6 +17,7 @@
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/cheerio": "0.22.2",
 | 
			
		||||
    "@types/jest": "20.0.2",
 | 
			
		||||
    "@types/node": "8.0.13",
 | 
			
		||||
    "@types/request": "0.0.47",
 | 
			
		||||
    "jest": "20.0.4",
 | 
			
		||||
    "jest-playback": "1.0.0",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										157
									
								
								src/create-cheat-sheet.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								src/create-cheat-sheet.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
			
		||||
import $ = require('cheerio');
 | 
			
		||||
import request = require('request');
 | 
			
		||||
 | 
			
		||||
// tslint:disable-next-line:no-var-requires
 | 
			
		||||
const package_json = require('../package.json');
 | 
			
		||||
 | 
			
		||||
const repo_name = package_json.name;
 | 
			
		||||
const repo_author = package_json.author;
 | 
			
		||||
 | 
			
		||||
const uncategorized = 'Uncategorized';
 | 
			
		||||
 | 
			
		||||
const api_url = 'https://api.github.com/emojis';
 | 
			
		||||
const sheet_url = 'http://www.emoji-cheat-sheet.com';
 | 
			
		||||
 | 
			
		||||
const travis_repo_url = `https://travis-ci.org/${repo_author}/${repo_name}`;
 | 
			
		||||
const travis_badge_url = `https://travis-ci.org/${repo_author}/${repo_name}.svg?branch=master`;
 | 
			
		||||
 | 
			
		||||
const url_descriptions = [
 | 
			
		||||
  ['GitHub Emoji API', api_url],
 | 
			
		||||
  ['Emoji Cheat Sheet', sheet_url],
 | 
			
		||||
].map(([site_name, site_url]) => `[${site_name}](${site_url})`).join(' and ');
 | 
			
		||||
 | 
			
		||||
// tslint:disable-next-line:max-line-length
 | 
			
		||||
const description = `This cheat sheet is automatically generated from ${url_descriptions}`;
 | 
			
		||||
 | 
			
		||||
const toc_name = 'Table of Contents';
 | 
			
		||||
 | 
			
		||||
const top_name = 'top';
 | 
			
		||||
const top_href = '#table-of-contents';
 | 
			
		||||
 | 
			
		||||
const column_divisions = 2;
 | 
			
		||||
 | 
			
		||||
type Url = string;
 | 
			
		||||
 | 
			
		||||
export interface Urls {
 | 
			
		||||
  [site_name: string]: Url;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface EmojiTable {
 | 
			
		||||
  [category: string]: string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function create_cheat_sheet() {
 | 
			
		||||
  const api_html = await get_html(api_url);
 | 
			
		||||
  const sheet_html = await get_html(sheet_url);
 | 
			
		||||
 | 
			
		||||
  const api_emojis = Object.keys(JSON.parse(api_html));
 | 
			
		||||
  const emoji_table: EmojiTable = {};
 | 
			
		||||
 | 
			
		||||
  const $html = $.load(sheet_html).root();
 | 
			
		||||
  $html.find('h2').each((_outer_index, category_element) => {
 | 
			
		||||
    const emojis: string[] = [];
 | 
			
		||||
    const category = $(category_element).text();
 | 
			
		||||
    $html.find(`#emoji-${category.toLowerCase()} li .name`).each((_inner_index, emoji_element) => {
 | 
			
		||||
      const emoji = $(emoji_element).text();
 | 
			
		||||
      const index = api_emojis.indexOf(emoji);
 | 
			
		||||
      if (index !== -1) {
 | 
			
		||||
        api_emojis.splice(index, 1);
 | 
			
		||||
        emojis.push(emoji);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    emoji_table[category] = emojis;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (api_emojis.length > 0) {
 | 
			
		||||
    emoji_table[uncategorized] = api_emojis;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return create_table(emoji_table);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_table(emoji_table: EmojiTable) {
 | 
			
		||||
  const categories = Object.keys(emoji_table);
 | 
			
		||||
  return format(`
 | 
			
		||||
 | 
			
		||||
    # ${repo_name}
 | 
			
		||||
 | 
			
		||||
    [](${travis_repo_url})
 | 
			
		||||
 | 
			
		||||
    ${description}
 | 
			
		||||
 | 
			
		||||
    ## ${toc_name}
 | 
			
		||||
 | 
			
		||||
    ${categories.map(category => `- [${category}](#${category.toLowerCase()})`).join('\n')}
 | 
			
		||||
 | 
			
		||||
    ${
 | 
			
		||||
      categories.map(category => {
 | 
			
		||||
        const emojis = emoji_table[category];
 | 
			
		||||
        return format(`
 | 
			
		||||
 | 
			
		||||
          ### ${category}
 | 
			
		||||
 | 
			
		||||
          ${create_table_head()}
 | 
			
		||||
          ${create_table_content(emojis)}
 | 
			
		||||
 | 
			
		||||
        `);
 | 
			
		||||
      }).join(('\n').repeat(2))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  `);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_table_content(emojis: string[]) {
 | 
			
		||||
  let table_content = '';
 | 
			
		||||
  for (let i = 0; i < emojis.length; i += column_divisions) {
 | 
			
		||||
    const row_emojis = emojis.slice(i, i + column_divisions);
 | 
			
		||||
    while (row_emojis.length < column_divisions) {
 | 
			
		||||
      row_emojis.push('');
 | 
			
		||||
    }
 | 
			
		||||
    table_content += `${format(`
 | 
			
		||||
 | 
			
		||||
    | [${top_name}](${top_href}) |${
 | 
			
		||||
      row_emojis.map(
 | 
			
		||||
        emoji => emoji.length !== 0
 | 
			
		||||
          ? ` :${emoji}: | \`:${emoji}:\` `
 | 
			
		||||
          : ' | ',
 | 
			
		||||
      ).join(' | ')
 | 
			
		||||
    }|
 | 
			
		||||
 | 
			
		||||
    `)}\n`;
 | 
			
		||||
  }
 | 
			
		||||
  return table_content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function create_table_head() {
 | 
			
		||||
  return format(`
 | 
			
		||||
 | 
			
		||||
  |   |${(' ico | emoji |').repeat(column_divisions)}
 | 
			
		||||
  | - |${(' --- | ----- |').repeat(column_divisions)}
 | 
			
		||||
 | 
			
		||||
  `);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function format(str: string) {
 | 
			
		||||
  return str.trim().replace(/^ +/mg, '');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function get_html(url: string) {
 | 
			
		||||
  return new Promise<string>((resolve, reject) => {
 | 
			
		||||
    const options = {url};
 | 
			
		||||
    if (url === api_url) {
 | 
			
		||||
      Object.assign(options, {
 | 
			
		||||
        headers: {'User-Agent': 'https://github.com/ikatyang/emoji-cheat-sheet'},
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    request.get(options, (error, response, html) => {
 | 
			
		||||
      if (error || response.statusCode !== 200) {
 | 
			
		||||
        const error_message = Boolean(error)
 | 
			
		||||
          ? error
 | 
			
		||||
          : `Unexpected response status code: ${response.statusCode}`;
 | 
			
		||||
        reject(error_message);
 | 
			
		||||
      } else {
 | 
			
		||||
        resolve(html);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@ -1,65 +0,0 @@
 | 
			
		||||
#!/bin/env node
 | 
			
		||||
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const $ = require('cheerio');
 | 
			
		||||
const request = require('request');
 | 
			
		||||
const markdown = require('./markdown');
 | 
			
		||||
 | 
			
		||||
const title = 'emoji-cheat-sheet';
 | 
			
		||||
const apiUrl = 'https://api.github.com/emojis';
 | 
			
		||||
const sheetUrl = 'http://www.emoji-cheat-sheet.com';
 | 
			
		||||
 | 
			
		||||
const outDir = path.resolve(process.cwd(), './generated');
 | 
			
		||||
const outFile = path.join(outDir, 'README.md');
 | 
			
		||||
 | 
			
		||||
const columnDivisions = 2;
 | 
			
		||||
 | 
			
		||||
const getHTML = (url) => new Promise((resolve, reject) => {
 | 
			
		||||
  const options = { url };
 | 
			
		||||
  if (url === apiUrl) {
 | 
			
		||||
    Object.assign(options, {
 | 
			
		||||
      headers: { 'User-Agent': 'https://github.com/ikatyang/emoji-cheat-sheet' },
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  request.get(options, (error, response, html) => {
 | 
			
		||||
    if (error || response.statusCode !== 200) {
 | 
			
		||||
      reject(error || `Unexpected response status code: ${response.statusCode}`);
 | 
			
		||||
    } else {
 | 
			
		||||
      resolve(html);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Promise.all([getHTML(apiUrl), getHTML(sheetUrl)]).then(([apiHTML, sheetHTML]) => {
 | 
			
		||||
  const apiEmojis = Object.keys(JSON.parse(apiHTML));
 | 
			
		||||
  const emojiTable = {};
 | 
			
		||||
  const $html = $.load(sheetHTML).root();
 | 
			
		||||
  $html.find('h2').each((_, categoryElement) => {
 | 
			
		||||
    const emojis = [];
 | 
			
		||||
    const category = $(categoryElement).text();
 | 
			
		||||
    $html.find(`#emoji-${category.toLowerCase()} li .name`).each((_, emojiElement) => {
 | 
			
		||||
      const emoji = $(emojiElement).text();
 | 
			
		||||
      const index = apiEmojis.indexOf(emoji);
 | 
			
		||||
      if (index !== -1) {
 | 
			
		||||
        apiEmojis.splice(index, 1);
 | 
			
		||||
        emojis.push(emoji);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    emojiTable[category] = emojis;
 | 
			
		||||
  });
 | 
			
		||||
  if (apiEmojis.length > 0) {
 | 
			
		||||
    emojiTable['Uncategorized'] = apiEmojis;
 | 
			
		||||
  }
 | 
			
		||||
  if (fs.existsSync(outDir)) {
 | 
			
		||||
    if (!fs.statSync(outDir).isDirectory()) {
 | 
			
		||||
      throw `OutDir '${outDir}' should be a directory.`;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    fs.mkdirSync(outDir);
 | 
			
		||||
  }
 | 
			
		||||
  fs.writeFileSync(outFile, markdown.create({
 | 
			
		||||
    'GitHub Emoji API': apiUrl,
 | 
			
		||||
    'Emoji Cheat Sheet': sheetUrl,
 | 
			
		||||
  }, title, emojiTable, columnDivisions));
 | 
			
		||||
});
 | 
			
		||||
@ -1,60 +0,0 @@
 | 
			
		||||
const format = str => str.trim().replace(/^ +/mg, '');
 | 
			
		||||
 | 
			
		||||
module.exports = class Markdown {
 | 
			
		||||
 | 
			
		||||
  static create(urls, title, emojiTable, columnDivisions) {
 | 
			
		||||
    const categories = Object.keys(emojiTable);
 | 
			
		||||
    const urlDescriptions = Object.keys(urls).map((site) => `[${site}](${urls[site]})`).join(' and ');
 | 
			
		||||
    return format(`
 | 
			
		||||
 | 
			
		||||
      # ${title}
 | 
			
		||||
 | 
			
		||||
      [](https://travis-ci.org/ikatyang/emoji-cheat-sheet)
 | 
			
		||||
 | 
			
		||||
      This cheat sheet is auto-generated from ${urlDescriptions} using [emoji-cheat-sheet-generator](https://github.com/ikatyang/emoji-cheat-sheet/tree/generator).
 | 
			
		||||
 | 
			
		||||
      ## Table of Contents
 | 
			
		||||
 | 
			
		||||
      ${categories.map(category => `- [${category}](#${category.toLowerCase()})`).join('\n')}
 | 
			
		||||
 | 
			
		||||
      ${
 | 
			
		||||
        categories.map(category => {
 | 
			
		||||
          const emojis = emojiTable[category];
 | 
			
		||||
          return format(`
 | 
			
		||||
 | 
			
		||||
            ### ${category}
 | 
			
		||||
 | 
			
		||||
            ${this.createTable(emojis, columnDivisions)}
 | 
			
		||||
 | 
			
		||||
          `);
 | 
			
		||||
        }).join(('\n').repeat(2))
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    `);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static createTableHead(columnDivisions) {
 | 
			
		||||
    return format(`
 | 
			
		||||
 | 
			
		||||
    |   |${(' ico | emoji |').repeat(columnDivisions)}
 | 
			
		||||
    | - |${(' --- | ----- |').repeat(columnDivisions)}
 | 
			
		||||
 | 
			
		||||
    `);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static createTable(emojis, columnDivisions) {
 | 
			
		||||
    let table = this.createTableHead(columnDivisions) + '\n';
 | 
			
		||||
    for (let i = 0; i < emojis.length; i += columnDivisions) {
 | 
			
		||||
      const rowEmojis = emojis.slice(i, i + columnDivisions);
 | 
			
		||||
      while (rowEmojis.length < columnDivisions)
 | 
			
		||||
        rowEmojis.push('');
 | 
			
		||||
      table += format(`
 | 
			
		||||
 | 
			
		||||
      | [top](#table-of-contents) |${rowEmojis.map((emoji) => emoji ? ` :${emoji}: | \`:${emoji}:\` ` : ' | ').join(' | ')}|
 | 
			
		||||
 | 
			
		||||
      `) + '\n';
 | 
			
		||||
    }
 | 
			
		||||
    return table;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
@ -47,7 +47,7 @@
 | 
			
		||||
  version "20.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-20.0.2.tgz#86c751121fb53dbd39bb1a08c45083da13f2dc67"
 | 
			
		||||
 | 
			
		||||
"@types/node@*":
 | 
			
		||||
"@types/node@*", "@types/node@8.0.13":
 | 
			
		||||
  version "8.0.13"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.13.tgz#530f0f9254209b0335bf5cc6387822594ef47093"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user