DEV: Populate table content using raw markdown (#7)
* Very exploratory MD work
* DEV: Populate table content using raw markdown
* DEV: 💄 Linting Fixes
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
This commit is contained in:
parent
69bfac2226
commit
98a9081e25
|
@ -6,9 +6,13 @@ import { iconNode } from "discourse-common/lib/icon-library";
|
|||
import { create } from "virtual-dom";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
import Session from "discourse/models/session";
|
||||
import loadScript from "discourse/lib/load-script";
|
||||
import PrettyText, { buildOptions } from "pretty-text/pretty-text";
|
||||
import { tokenRange } from "../lib/utilities";
|
||||
export default apiInitializer("0.11.1", (api) => {
|
||||
const site = api.container.lookup("site:main");
|
||||
const site = api.container.lookup("site:main"),
|
||||
siteSettings = api.container.lookup("site-settings:main");
|
||||
|
||||
function createButton() {
|
||||
const openPopupBtn = document.createElement("button");
|
||||
|
@ -35,12 +39,26 @@ export default apiInitializer("0.11.1", (api) => {
|
|||
|
||||
return ajax(`/posts/${this.id}`, { type: "GET" })
|
||||
.then((post) => {
|
||||
showModal("insert-table-modal", {
|
||||
model: post,
|
||||
}).setProperties({
|
||||
tableHtml: tempTable,
|
||||
tableId,
|
||||
});
|
||||
let markdownItURL = Session.currentProp("markdownItURL");
|
||||
|
||||
if (markdownItURL) {
|
||||
loadScript(markdownItURL).then(() => {
|
||||
const prettyText = new PrettyText(buildOptions({ siteSettings }));
|
||||
const tokens = prettyText.opts.engine.parse(post.raw, {
|
||||
references: {},
|
||||
});
|
||||
const allTables = tokenRange(tokens, "table_open", "table_close");
|
||||
const tableTokens = allTables[tableId];
|
||||
|
||||
showModal("insert-table-modal", {
|
||||
model: post,
|
||||
}).setProperties({
|
||||
tableHtml: tempTable,
|
||||
tableId,
|
||||
tableTokens,
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { action } from "@ember/object";
|
||||
import loadScript from "discourse/lib/load-script";
|
||||
import { arrayToTable, findTableRegex, tableToObj } from "../lib/utilities";
|
||||
import { arrayToTable, findTableRegex, tokenRange } from "../lib/utilities";
|
||||
import GlimmerComponent from "discourse/components/glimmer";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
@ -49,7 +49,7 @@ export default class SpreadsheetEditor extends GlimmerComponent {
|
|||
schedule("afterRender", () => {
|
||||
this.loadLibraries().then(() => {
|
||||
if (this.isEditingTable) {
|
||||
this.buildPopulatedTable(this.args.tableHtml);
|
||||
this.buildPopulatedTable(this.args.tableTokens);
|
||||
} else {
|
||||
this.buildNewTable();
|
||||
}
|
||||
|
@ -108,29 +108,46 @@ export default class SpreadsheetEditor extends GlimmerComponent {
|
|||
return this.buildSpreadsheet(data, columns);
|
||||
}
|
||||
|
||||
buildPopulatedTable(table) {
|
||||
const tableObject = tableToObj(table);
|
||||
const headings = [];
|
||||
const tableData = [];
|
||||
extractTableContent(data) {
|
||||
return data
|
||||
.flat()
|
||||
.filter((t) => t.type === "inline")
|
||||
.map((t) => t.content);
|
||||
}
|
||||
|
||||
tableObject.forEach((object) => {
|
||||
// Build Headings
|
||||
if (!headings.includes(...Object.keys(object))) {
|
||||
headings.push(...Object.keys(object));
|
||||
buildPopulatedTable(tableTokens) {
|
||||
const contentRows = tokenRange(tableTokens, "tr_open", "tr_close");
|
||||
const rows = [];
|
||||
let headings;
|
||||
const rowWidthFactor = 8;
|
||||
|
||||
contentRows.forEach((row, index) => {
|
||||
if (index === 0) {
|
||||
// headings
|
||||
headings = this.extractTableContent(row).map((heading) => {
|
||||
return {
|
||||
title: heading,
|
||||
width: heading.length * rowWidthFactor,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
// rows:
|
||||
const rowContent = this.extractTableContent(row);
|
||||
|
||||
// If row content is larger than header, update column width:
|
||||
rowContent.forEach((c, i) => {
|
||||
const colWidth = rowContent[i].length * rowWidthFactor;
|
||||
|
||||
if (headings[i].width < colWidth) {
|
||||
headings[i].width = colWidth;
|
||||
}
|
||||
});
|
||||
|
||||
rows.push(rowContent);
|
||||
}
|
||||
|
||||
// Build Table Data
|
||||
tableData.push([...Object.values(object)]);
|
||||
});
|
||||
|
||||
const columns = headings.map((heading) => {
|
||||
return {
|
||||
title: heading,
|
||||
width: heading.length * 15,
|
||||
};
|
||||
});
|
||||
|
||||
return this.buildSpreadsheet(tableData, columns);
|
||||
return this.buildSpreadsheet(rows, headings);
|
||||
}
|
||||
|
||||
buildSpreadsheet(data, columns, opts = {}) {
|
||||
|
|
|
@ -1,43 +1,5 @@
|
|||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Generate an object from an HTML table
|
||||
*
|
||||
* @see {@link https://gist.github.com/mattheo-gist/4151867|GitHub}
|
||||
*
|
||||
* @param {Table} table HTML Table element
|
||||
*
|
||||
* @return {Object} A JavaScript object
|
||||
*/
|
||||
export function tableToObj(table) {
|
||||
var rows = table.rows;
|
||||
var propCells = rows[0].cells;
|
||||
var propNames = [];
|
||||
var results = [];
|
||||
var obj, row, cells;
|
||||
|
||||
// Use the first row for the property names
|
||||
// Could use a header section but result is the same if
|
||||
// there is only one header row
|
||||
for (var i = 0, iLen = propCells.length; i < iLen; i++) {
|
||||
propNames.push(propCells[i].textContent || propCells[i].innerText);
|
||||
}
|
||||
|
||||
// Use the rows for data
|
||||
// Could use tbody rows here to exclude header & footer
|
||||
// but starting from 1 gives required result
|
||||
for (var j = 1, jLen = rows.length; j < jLen; j++) {
|
||||
cells = rows[j].cells;
|
||||
obj = {};
|
||||
|
||||
for (var k = 0; k < iLen; k++) {
|
||||
obj[propNames[k]] = cells[k].textContent || cells[k].innerText;
|
||||
}
|
||||
results.push(obj);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate markdown table from an array of objects
|
||||
*
|
||||
|
@ -93,3 +55,27 @@ export function arrayToTable(array, columns, alignment = "center") {
|
|||
export function findTableRegex() {
|
||||
return /((\r?){2}|^)([^\r\n]*\|[^\r\n]*(\r?\n)?)+(?=(\r?\n){2}|$)/gm;
|
||||
}
|
||||
|
||||
export function tokenRange(tokens, start, end) {
|
||||
const contents = [];
|
||||
let startPushing = false;
|
||||
let items = [];
|
||||
|
||||
tokens.forEach((token) => {
|
||||
if (token.type === start) {
|
||||
startPushing = true;
|
||||
}
|
||||
|
||||
if (token.type === end) {
|
||||
contents.push(items);
|
||||
items = [];
|
||||
startPushing = false;
|
||||
}
|
||||
|
||||
if (startPushing) {
|
||||
items.push(token);
|
||||
}
|
||||
});
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<SpreadsheetEditor
|
||||
@model={{this.model}}
|
||||
@tableHtml={{this.tableHtml}}
|
||||
@tableTokens={{this.tableTokens}}
|
||||
@tableId={{this.tableId}}
|
||||
@triggerModalClose={{action "closeEditModal"}}
|
||||
@toolbarEvent={{this.toolbarEvent}}
|
||||
|
|
Loading…
Reference in New Issue