mirror of
https://github.com/meld-cp/obsidian-build.git
synced 2026-07-22 07:30:25 +00:00
add markdown helper, fix spelling
This commit is contained in:
parent
26d267aca5
commit
fb09699c1b
10 changed files with 195 additions and 48 deletions
|
|
@ -197,6 +197,15 @@ const result = await $.markers.apply();
|
|||
```
|
||||
````
|
||||
|
||||
## Markdown Helper (`$.md`)
|
||||
|
||||
- `$.md.table( headers:[], rows:[[]])`
|
||||
- Build a markdown table
|
||||
- e.g. `$.md.table( ['header 1', 'header2'], rows:[ ['row 1 col 1', 'row 1 col 2'], ['row 2 col 1', 'row 2 col 2'], ])`
|
||||
- `$.md.table( data )`
|
||||
- Build a markdown table from imported data
|
||||
- e.g. `$.md.table( $.data.customers )`
|
||||
|
||||
## Assert (`$.assert`)
|
||||
|
||||
You can use `$.assert` to stop the run and show a message if a test fails.
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import { RunLogger } from 'src/run-logger';
|
|||
import { TRunContext } from "src/run-context";
|
||||
import { NamedCodeBlock } from "./named-code-block";
|
||||
import { CodeBlockInfoHelper } from "./code-block-info";
|
||||
import { AssertRunContextImplemention } from "./rci-assert";
|
||||
import { UiRunContextImplemention } from "./rci-ui";
|
||||
import { IoRunContextImplemention } from "./rci-io";
|
||||
import { MarkerRunContextImplemention } from "./rci-markers";
|
||||
import { AssertRunContextImplementation } from "./rci-assert";
|
||||
import { UiRunContextImplementation } from "./rci-ui";
|
||||
import { IoRunContextImplementation } from "./rci-io";
|
||||
import { MarkerRunContextImplementation } from "./rci-markers";
|
||||
import { MarkdownHelperRunContextImplementation } from "./rci-markdown";
|
||||
|
||||
export class Compiler{
|
||||
|
||||
|
|
@ -142,11 +143,11 @@ export class Compiler{
|
|||
return '';
|
||||
},
|
||||
|
||||
assert: new AssertRunContextImplemention(),
|
||||
assert: new AssertRunContextImplementation(),
|
||||
|
||||
ui: new UiRunContextImplemention(),
|
||||
ui: new UiRunContextImplementation(),
|
||||
|
||||
io: new IoRunContextImplemention(
|
||||
io: new IoRunContextImplementation(
|
||||
view.app.vault,
|
||||
view.app.workspace,
|
||||
log,
|
||||
|
|
@ -154,13 +155,15 @@ export class Compiler{
|
|||
consumableBlocks
|
||||
),
|
||||
|
||||
markers: new MarkerRunContextImplemention(
|
||||
markers: new MarkerRunContextImplementation(
|
||||
view.app.vault,
|
||||
log,
|
||||
view.file.path
|
||||
),
|
||||
|
||||
dv: dvGetAPI(),
|
||||
|
||||
md: new MarkdownHelperRunContextImplementation( log )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,23 @@
|
|||
export class DataSet extends Array<DataSetRow> {
|
||||
|
||||
public columns:string[] = [];
|
||||
|
||||
constructor( columnNames:string[] ){
|
||||
|
||||
super();
|
||||
|
||||
this.columns = columnNames.map( cn => cn.trim() );
|
||||
|
||||
}
|
||||
|
||||
private extractAsColumnName( str:string ) : string {
|
||||
return str.trim().replaceAll(/\W/ig, '_').toLowerCase().trim();
|
||||
}
|
||||
|
||||
public getPropertyName ( colName:string ) : string | undefined {
|
||||
return this.extractAsColumnName( colName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface IDataSetCollection {
|
||||
|
|
@ -14,12 +32,13 @@ export class DataSetRow implements IRowDataValueCollection{
|
|||
|
||||
[column: string]: unknown;
|
||||
|
||||
constructor(columnNames:string[], data: unknown[]){
|
||||
for (let colIdx = 0; colIdx < columnNames.length; colIdx++) {
|
||||
const value = data.at(colIdx);
|
||||
const colName = columnNames[colIdx].trim();
|
||||
if ( colName != '' ){
|
||||
this[colName] = value;
|
||||
constructor( dataSet:DataSet, values: unknown[] ){
|
||||
const columns = dataSet.columns;
|
||||
for ( let colIdx = 0; colIdx < columns.length; colIdx++ ) {
|
||||
const rawColName = columns[colIdx];
|
||||
const propColName = dataSet.getPropertyName(rawColName);
|
||||
if ( propColName !== undefined ){
|
||||
this[propColName] = values.at(colIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,20 +104,20 @@ export class Parser {
|
|||
public loadCsv( csvContent:string ) : DataSet {
|
||||
const lines = csvContent.split('\n').map( e=>e.trim() );
|
||||
if (lines.length == 0){
|
||||
return new DataSet();
|
||||
return new DataSet( [] );
|
||||
}
|
||||
|
||||
const columns = lines.first()?.split(',').map( e => this.extractAsColumnName(e) ) ?? [];
|
||||
const columns = lines.first()?.split(',') ?? [];
|
||||
|
||||
const rows = new Array<DataSetRow>();
|
||||
const ds = new DataSet( columns );
|
||||
|
||||
//const rows = new Array<DataSetRow>();
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const rowData = lines[i].split(',').map( d => this.extractValueFromString(d));
|
||||
rows.push( new DataSetRow(columns, rowData));
|
||||
ds.push( new DataSetRow(ds, rowData));
|
||||
}
|
||||
|
||||
const ds = new DataSet( ...rows );
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
|
|
@ -181,19 +181,15 @@ export class Parser {
|
|||
}
|
||||
|
||||
private parseMdTable( tableLines:string[] ): DataSet {
|
||||
const data: DataSet = new DataSet();
|
||||
|
||||
const tlines = tableLines
|
||||
.map( e=>e.trim().slice(1,-1).trim());
|
||||
const tlines = tableLines.map( e=>e.trim().slice(1,-1).trim());
|
||||
|
||||
const columns = tlines.first()?.split('|') ?? [];
|
||||
|
||||
const data: DataSet = new DataSet( columns );
|
||||
|
||||
const columns = tlines
|
||||
.first()?.split('|')
|
||||
.map( e=> this.extractAsColumnName(e) )
|
||||
.filter( e=>e.length > 0)
|
||||
?? []
|
||||
;
|
||||
|
||||
for (let i = 1; i < tlines.length; i++) {
|
||||
for (let i = 2; i < tlines.length; i++) {
|
||||
const rowLine = tlines[i];
|
||||
if (rowLine.startsWith('---') ){
|
||||
continue;
|
||||
|
|
@ -202,7 +198,7 @@ export class Parser {
|
|||
continue;
|
||||
}
|
||||
const rowValues : unknown[] = rowLine.split('|').map( e => this.extractValueFromString(e) );
|
||||
data.push( new DataSetRow( columns, rowValues ) );
|
||||
data.push( new DataSetRow( data, rowValues ) );
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
@ -287,10 +283,6 @@ export class Parser {
|
|||
return str.trim().replaceAll(/\W/ig, '_').toLowerCase();
|
||||
}
|
||||
|
||||
private extractAsColumnName( str:string ) : string {
|
||||
return str.trim().replaceAll(/\W/ig, '_').toLowerCase();
|
||||
}
|
||||
|
||||
private extractValueFromString( str:string ) : string | number | Date {
|
||||
const trimmed = str.trim();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MessageModal } from "./modal-message";
|
||||
import { TAssertRunContext } from "./run-context";
|
||||
|
||||
export class AssertRunContextImplemention implements TAssertRunContext {
|
||||
export class AssertRunContextImplementation implements TAssertRunContext {
|
||||
|
||||
private async showFailMessage( label:string, msg:string ) : Promise<void>{
|
||||
const title = '❗ Assert Failed' + ( label.length > 0 ? ` - ${label}` : '' );
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { TIoRunContext } from "./run-context";
|
|||
import { RunLogger } from "./run-logger";
|
||||
import { Utils } from "./utils";
|
||||
|
||||
export class IoRunContextImplemention implements TIoRunContext {
|
||||
export class IoRunContextImplementation implements TIoRunContext {
|
||||
|
||||
private vault: Vault;
|
||||
private workspace: Workspace;
|
||||
|
|
@ -32,25 +32,27 @@ export class IoRunContextImplemention implements TIoRunContext {
|
|||
}
|
||||
|
||||
private async data_loader(filepath:string, name?:string) : Promise<DataSet>{
|
||||
let resultDataSet = new DataSet();
|
||||
|
||||
|
||||
const absFilepath = this.getAbsoluteFilepathFromActiveFile(filepath);
|
||||
if (!absFilepath){
|
||||
return resultDataSet;
|
||||
return new DataSet([]);
|
||||
}
|
||||
|
||||
|
||||
const file = this.vault.getAbstractFileByPath(absFilepath);
|
||||
|
||||
|
||||
const pzr = new Parser();
|
||||
|
||||
if (file instanceof TFile){
|
||||
if (file.extension == 'csv'){
|
||||
|
||||
if ( file.extension == 'csv'){
|
||||
const csvdata = await this.vault.read( file );
|
||||
resultDataSet = pzr.loadCsv(csvdata);
|
||||
this.data[name??file.basename] = resultDataSet;
|
||||
const dataSet = pzr.loadCsv(csvdata);
|
||||
this.data[name??file.basename] = dataSet;
|
||||
return dataSet;
|
||||
}
|
||||
}
|
||||
|
||||
return resultDataSet;
|
||||
return new DataSet([]);
|
||||
}
|
||||
|
||||
async import(path: string): Promise<boolean> {
|
||||
|
|
|
|||
114
src/rci-markdown.ts
Normal file
114
src/rci-markdown.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
import { DataSet } from "./data-set";
|
||||
import { TMarkdownHelperRunContext } from "./run-context";
|
||||
import { RunLogger } from "./run-logger";
|
||||
|
||||
export class MarkdownHelperRunContextImplementation implements TMarkdownHelperRunContext{
|
||||
|
||||
private log: RunLogger;
|
||||
|
||||
constructor( log: RunLogger ){
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
private buildTable(headings: string[], rows: any[][]): string{
|
||||
return MarkdownTableHelper.buildTable( headings, rows );
|
||||
}
|
||||
|
||||
buildTableFromDataSet(data: DataSet): string {
|
||||
const headings = data.columns;
|
||||
const rowValues : any[][] = [];
|
||||
|
||||
for (const row of data) {
|
||||
const values : any[] = [];
|
||||
|
||||
for (const heading of headings) {
|
||||
const prop = data.getPropertyName(heading);
|
||||
const value = prop == undefined ? undefined : row[prop];
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
rowValues.push( values );
|
||||
}
|
||||
|
||||
return MarkdownTableHelper.buildTable( headings, rowValues );
|
||||
}
|
||||
|
||||
public table(arg1: unknown, arg2?: unknown): string {
|
||||
if (arg1 instanceof DataSet){
|
||||
return this.buildTableFromDataSet(arg1);
|
||||
}
|
||||
if ( Array.isArray(arg1) && Array.isArray(arg2) ){
|
||||
return this.buildTable(arg1, arg2);
|
||||
}
|
||||
throw new Error('Invalid args for markdown table');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MarkdownTableHelper {
|
||||
|
||||
|
||||
public static buildTable(headings: string[], rowValues: any[][]): string{
|
||||
|
||||
const headers = MarkdownTableHelper.buildHeaderRows( headings );
|
||||
const rows = MarkdownTableHelper.buildValueRows( rowValues );
|
||||
|
||||
const lines = [
|
||||
'',
|
||||
...headers,
|
||||
...rows,
|
||||
'',
|
||||
]
|
||||
|
||||
console.debug({lines});
|
||||
|
||||
return lines.join('\n');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static removeHeaderFormat( header: string ) : string {
|
||||
if ( header.startsWith('<') || header.startsWith('>') ){
|
||||
return header.slice(1);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
private static buildFormatRowCell( header: string ): string {
|
||||
let leftMarker = ' ';
|
||||
let rightMarker = ' ';
|
||||
|
||||
if ( header.startsWith('<') ){
|
||||
leftMarker = ':';
|
||||
header = header.slice(1);
|
||||
} else if ( header.startsWith('>') ){
|
||||
rightMarker = ':';
|
||||
header = header.slice(1);
|
||||
}else{
|
||||
leftMarker = ':';
|
||||
rightMarker = ':';
|
||||
header = header;
|
||||
}
|
||||
|
||||
return leftMarker + '-'.repeat( header.length ) + rightMarker;
|
||||
}
|
||||
|
||||
private static buildHeaderRows( formattedHeadings: string[] ) : string[] {
|
||||
var result : string[] = [];
|
||||
result.push( '|' + formattedHeadings.map( header => ` ${MarkdownTableHelper.removeHeaderFormat(header)} ` ).join('|') + '|' );
|
||||
result.push( '|' + formattedHeadings.map( header => MarkdownTableHelper.buildFormatRowCell(header) ).join('|') + '|' );
|
||||
return result;
|
||||
}
|
||||
|
||||
private static buildValueRow( rowValues: any[] ) : string {
|
||||
return '|' + rowValues.map( c => ` ${c} ` ).join('|') + '|';
|
||||
}
|
||||
|
||||
|
||||
private static buildValueRows( valueRows: any[][] ) : string[] {
|
||||
return valueRows.map( rowValues => MarkdownTableHelper.buildValueRow(rowValues) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import { TFile, Vault } from "obsidian";
|
|||
import { MarkerChange, MarkerValue, TMarkerRunContext } from "./run-context";
|
||||
import { RunLogger } from "./run-logger";
|
||||
|
||||
export class MarkerRunContextImplemention implements TMarkerRunContext {
|
||||
export class MarkerRunContextImplementation implements TMarkerRunContext {
|
||||
|
||||
private markerStartPrefix = '%%';
|
||||
private markerStartSuffix = '=%%';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { AskModal } from "./modal-ask";
|
|||
import { MessageModal } from "./modal-message";
|
||||
import { TUiRunContext } from "./run-context";
|
||||
|
||||
export class UiRunContextImplemention implements TUiRunContext {
|
||||
export class UiRunContextImplementation implements TUiRunContext {
|
||||
|
||||
notice(
|
||||
message: string | DocumentFragment,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ export type TRunContext = {
|
|||
|
||||
dv: DataviewApi | undefined;
|
||||
|
||||
md: TMarkdownHelperRunContext;
|
||||
|
||||
}
|
||||
|
||||
export type TUiRunContext = {
|
||||
|
|
@ -116,3 +118,9 @@ export class MarkerChange{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export type TMarkdownHelperRunContext = {
|
||||
table( headings:Array<string>, rows:Array<Array<any>> ) : string;
|
||||
table( data:DataSet ) : string;
|
||||
}
|
||||
Loading…
Reference in a new issue