扒公众号文章的Console代码

  (function() {
    const el = document.querySelector('#js_content').cloneNode(true);

    // 删除行号
    el.querySelectorAll('.code-snippet__line-index').forEach(u => u.remove());

    // 代码块替换为占位标记
    el.querySelectorAll('section.code-snippet__fix').forEach(sec => {
      const pre = sec.querySelector('pre');
      if (!pre) return;
      const lang = pre.getAttribute('data-lang') || '';
      const lines = [...pre.querySelectorAll('code')].map(c => c.textContent);
      const ph = document.createElement('div');
      ph.setAttribute('data-md-code', lang);
      ph.textContent = lines.join('\n');
      sec.replaceWith(ph);
    });

    function convert(node) {
      if (node.nodeType === Node.TEXT_NODE) {
        return node.textContent;
      }
      if (node.nodeType !== Node.ELEMENT_NODE) return '';

      const tag = node.tagName.toLowerCase();
      if (tag === 'script' || tag === 'style') return '';

      // 代码块占位
      if (node.hasAttribute('data-md-code')) {
        const lang = node.getAttribute('data-md-code');
        return '\n\n```' + lang + '\n' + node.textContent + '\n```\n\n';
      }

      const inner = [...node.childNodes].map(convert).join('');
      const text = inner.trim();

      switch (tag) {
        case 'p':
        case 'div':
          return '\n\n' + text + '\n\n';
        case 'br':
          return '\n';
        case 'strong':
        case 'b':
          return text ? '**' + text + '**' : '';
        case 'em':
        case 'i':
          return text ? '*' + text + '*' : '';
        case 'code':
          return '`' + text + '`';
        case 'h1': return '\n\n# ' + text + '\n\n';
        case 'h2': return '\n\n## ' + text + '\n\n';
        case 'h3': return '\n\n### ' + text + '\n\n';
        case 'h4': return '\n\n#### ' + text + '\n\n';
        case 'h5': return '\n\n##### ' + text + '\n\n';
        case 'h6': return '\n\n###### ' + text + '\n\n';
        case 'blockquote':
          return '\n\n' + text.split('\n').map(l => '> ' + l).join('\n') + '\n\n';
        case 'ul':
        case 'ol':
          return '\n\n' + inner + '\n';
        case 'li': {
          const p = node.parentElement;
          if (p && p.tagName.toLowerCase() === 'ol') {
            const i = [...p.children].indexOf(node) + 1;
            return i + '. ' + text + '\n';
          }
          return '- ' + text + '\n';
        }
        case 'a': {
          const href = node.getAttribute('href') || '';
          return '[' + text + '](' + href + ')';
        }
        case 'img': {
          const src = node.getAttribute('data-src') || node.getAttribute('src') || '';
          const alt = node.getAttribute('alt') || '';
          return '\n\n![' + alt + '](' + src + ')\n\n';
        }
        case 'hr':
          return '\n\n---\n\n';
        default:
          return inner;
      }
    }

    let md = convert(el)
      .replace(/\n{3,}/g, '\n\n')
      .trim();

    copy(md);
    console.log('已复制到剪贴板,共 ' + md.length + ' 字符');
  })();