Use the Chrome plugin to complement some writing sites that don't have Markdown pits

scene

Technicians can write articles like Markdown, but many of the self-Media platforms (big and all) are pot dad's rich text editors (and many are UEditor s who have not been updated officially for three years).

Like this:

It's a hassle, especially for editors that don't have code blocks, and that's right, it's you, headlines!This kind of shit has to let the programmer paste the code in manually, and then encounter unfriendly typesetting, heh, yeah, it's you, headline!
So I thought, Grandma's a bear, I would write a plug-in myself without it.

In fact, it's good that I have a set of editors on my own website that I rely on marked to do, but because of the graphics bed problem, I still have to paste rich text into the headlines every time, delete pictures, upload them again, and I can't help but live my life.
Cough and finally come out, but find no eggs to use...Meow, Markdown has a code block, but people's rich text doesn't support it...In a word, write it and share your ideas.

frame

manifest.json configuration

{
  "name": "Today's Headline Collaboration Assistant",
  "version": "1.0.0",
  "description": "Supplement to the missing collaboration tools for today's front page edition.",
  "permissions": [
    "activeTab",
    "declarativeContent"
  ],
  "content_scripts": [
    {
      "matches": [
        "https://mp.toutiao.com/*"
      ],
      "js": [
        "js/util.js",
        "libs/turndown.js",
        "js/content/index.js"
      ],
      "css": [],
      "run_at": "document_start"
    }
  ],
  "browser_action": {
    "default_popup": "popup.html",
    "default_title": "This can complement the shortage of the headline version.",
    "default_icon": {
      "16": "img/logo_16.png",
      "32": "img/logo_32.png",
      "48": "img/logo_48.png",
      "128": "img/logo_128.png"
    }
  },
  "homepage_url": "https://www.kvker.com/",
  "icons": {
    "16": "img/logo_16.png",
    "32": "img/logo_32.png",
    "48": "img/logo_48.png",
    "128": "img/logo_128.png"
  },
  "manifest_version": 2
}

The main thing here is to look at content_scripts, which is called scripts. As you can see, you can plug in some css, but just look at js here.
Utl.js mainly provides a function to be used when editing to avoid the Markdown2HTML, or debounce jitter, being escaped every time an edit triggers an input.

The core is as follows (with throttle throttle):

let doLastTimeout
let doLastOperates = []

let timeout = 500

let kvkerUtil = {
  /**
   * Multiple operations performed asynchronously, only the last, such as input content retrieval
   * @param {function} operate Incoming Operation
   * @param {number} idx (Optional) Perform a feature index number operation, which is not normally used
   */
  doAsyncLast(operate, time = 500, idx) {
    if (typeof operate !== 'function') {
      throw 'implement doLast Function error: need to pass in function!'
    }
    clearTimeout(doLastTimeout)
    doLastTimeout = setTimeout(() => {
      let lastOperate = doLastOperates[doLastOperates.length - 1]
      lastOperate()
      doLastOperates = []
      clearTimeout(doLastTimeout)
      doLastTimeout = null
    }, time)
    doLastOperates.push(operate)
  },
  /**
   * Multiple operations performed synchronously in one instant, only the last one, such as multiple network requests returning at the same time and prompting for a message
   * @param {function} operate Incoming Operation
   * @param {number} idx (Optional) Perform a feature index number operation, which is not normally used
   */
  doSyncLast(operate, time = 500, idx) {
    if (typeof operate !== 'function') {
      throw 'implement doLast Function error: need to pass in function!'
    }
    if (!doLastTimeout) {
      doLastTimeout = setTimeout(() => {
        let lastOperate = doLastOperates[doLastOperates.length - 1]
        lastOperate()
        doLastOperates = []
        clearTimeout(doLastTimeout)
        doLastTimeout = null
      }, time)
    }
    doLastOperates.push(operate)
  },
}

Then turndown.js, which is the reverse of marked.js.Marked is Markdown2HTML, then turndown is HTML2Markdown.This kind of thing is certainly a wheel, safe and useful (npm).

As far as content/index.js is concerned, it is the JS inserted on the core page (either inject, which is not as good as inject, let's not elaborate here), or the functions that the document runs with, typically, document_start.Says js, who later combines plugins.

The last thing this file does is look at popup.html, which is a random area of the file name to click on the small window shown by the plug-in and look at FeHelper like this:

Look at the following:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Popup</title>
  <style>
    * {
      box-sizing: border-box !important;
    }
    body {
      margin: 0;
      padding: 4px;
    }
    #textarea {
      resize: none;
      outline: none;
      padding: 8px;
    }
  </style>
</head>

<body>
  <h1>Headlines Markdown editor</h1>
  <textarea id="textarea" cols="80" rows="30"></textarea>

  <script src="libs/marked.js"></script>
  <script src="js/popup.js"></script>
</body>

</html>

General content, long like this:

Just one input box and header, no, listen for this input box change.

Then introduce js, not to mention marked.js, popup.js is the core JS of this page, which is described in detail below.

At this point, the feature page is fully resourced (not to mention icon).

logic

  1. The page input of the plug-in is synchronized to the input box of the web page, and since the input box of the web page is rich text, it must be HTML characters after Markdown2HTML ization.
  2. When the web page starts, because content/index.js loads earlier than rich text generation, find a way to get a label for rich text;
  3. When the web page starts, if there is a draft, HTML2Markdown the content of the draft to the plug-in input box;
  4. Based on 3, you have to prompt the user to open the popup page (plug-in page) before passing HTML2Markdown, or it will go to the ghost (plug-in pages open and close are rerun pages).

With a total of the above four core issues addressed, this simple plug-in is complete (although there are no eggs to use).

Question 1

popup.js

let editor = document.querySelector('#textarea')

// Listen for input, pass it to content/index.js, and receive callback backs for backup
editor.addEventListener('input', e => {
  sendMessageToContentScript({ cmd: 'test', value: marked(e.target.value) }, function(response) {
    console.log('Come from content Reply:' + response)
  })
})

// Send a message to content/index.js
function sendMessageToContentScript(message, callback) {
  chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
    chrome.tabs.sendMessage(tabs[0].id, message, function(response) {
      if(callback) callback(response)
    })
  })
}

// Listen for draft page generation...
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  editor.value = request.value
  sendResponse('I am popup´╝îI have received your message:' + JSON.stringify(request))
})

Specifically, they are api of chrome plug-ins, mainly depending on logic.

Questions 2, 3, 4

content/index.js

let sourceEditor
// Check if the editor is loaded every second
let interval = setInterval(() => {
  if(sourceEditor) {
    // Use alert prompt and interrupt the run to give the user time to open the plugin...Am I smart?
    alert('Once the plug-in is loaded, open the plug-in and close the pop-up window')
    clearInterval(interval)
    // Send draft to popup
    sendInitialContent({cmd: 'initialData', value: new TurndownService().turndown(sourceEditor.innerHTML)})
  } else {
    sourceEditor = document.querySelector('.ql-editor')
  }
}, 1000)

function sendInitialContent(message) {
  chrome.runtime.sendMessage(message, function(response) {
    console.log('Receive a response from the background:' + response)
  })
}

// Listen for messages from popup
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if(request.cmd === 'test') {
    console.log(request.value)
    kvkerUtil.doAsyncLast(() => sourceEditor.innerHTML = request.value)
  }
  sendResponse('I received your message!')
})

Yes, what alert is the soul, YES!

Effect

The bug is there because I didn't optimize it, and it didn't work anyway.And the rich text label on the headline is amazing. You have to change Mark.js to Magic.

It's about sharing logic and familiarizing yourself with chrome's api.

Interesting, you can scratch the source research, there may be no platform you are interested in making a full version of ~

Resources

Headline Plugin v0.0.1 Source

Tags: Javascript JSON network npm IE

Posted on Sat, 31 Aug 2019 12:07:25 -0700 by crislewis