hop
This commit is contained in:
parent
37fc569fa3
commit
8c603e291e
19
README.md
19
README.md
|
@ -16,10 +16,10 @@ pour le lancer: npm start.
|
||||||
* avoir Nodejs en version stable et installer les modules node.
|
* avoir Nodejs en version stable et installer les modules node.
|
||||||
|
|
||||||
# Utilisation
|
# Utilisation
|
||||||
## Configuration
|
## Configuration
|
||||||
Vérifiez les variables de chemin dans **parse_orgmode_to_json.mjs**, surtout outputAbsolutePath pour avoir un lieu de génération de fichier.
|
Vérifiez les variables de chemin dans **parse_orgmode_to_json.mjs**, surtout outputAbsolutePath pour avoir un lieu de génération de fichier.
|
||||||
|
|
||||||
## compiler les fichiers org et les convertir en json
|
## compiler les fichiers org et les convertir en json
|
||||||
Il suffit de lancer cette commande du Makefile
|
Il suffit de lancer cette commande du Makefile
|
||||||
```bash
|
```bash
|
||||||
make convert
|
make convert
|
||||||
|
@ -28,8 +28,8 @@ Elle réalise la concaténation des fichiers tasks.org et tasks.org_archive fait
|
||||||
|
|
||||||
la sortie est générée dans "outputAbsolutePath" définie dans "parse_orgmode_to_json.mjs"
|
la sortie est générée dans "outputAbsolutePath" définie dans "parse_orgmode_to_json.mjs"
|
||||||
|
|
||||||
## Données générées
|
## Données générées
|
||||||
### Des statistiques
|
### Des statistiques
|
||||||
|
|
||||||
* Les nombres et le type de tâches agrégées par semaine, mois et années.
|
* Les nombres et le type de tâches agrégées par semaine, mois et années.
|
||||||
* le nombre de tâches avec une date.
|
* le nombre de tâches avec une date.
|
||||||
|
@ -41,20 +41,17 @@ la sortie est générée dans "outputAbsolutePath" définie dans "parse_orgmode_
|
||||||
* Les nombres de fois que des mots sont utilisés dans les tâches.
|
* Les nombres de fois que des mots sont utilisés dans les tâches.
|
||||||
* des données sur l'auteur, la date de génération du json, le fichier source .org ayant servi à la conversion.
|
* des données sur l'auteur, la date de génération du json, le fichier source .org ayant servi à la conversion.
|
||||||
|
|
||||||
|
## voir le rendu
|
||||||
###
|
|
||||||
|
|
||||||
## voir le rendu
|
|
||||||
Lancer l'exécution du fichier app avec node, et consulter l'output html.
|
Lancer l'exécution du fichier app avec node, et consulter l'output html.
|
||||||
```bash
|
```bash
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
## Memacs
|
## Memacs
|
||||||
Les scripts inspirés de Memacs (le package python-pip) sont dans le dossier **converters**, ils permettent de convertir des fichiers exportés de divers outils numériques en feuilles de calcul pour avoir un historique général d'activités simple à lire pour les humains, et facile à analyser pour d'autres scripts.
|
Les scripts inspirés de Memacs (le package python-pip) sont dans le dossier **converters**, ils permettent de convertir des fichiers exportés de divers outils numériques en feuilles de calcul pour avoir un historique général d'activités simple à lire pour les humains, et facile à analyser pour d'autres scripts.
|
||||||
|
|
||||||
|
|
||||||
# feuille de route TODO
|
# feuille de route TODO
|
||||||
Proposer une sortie json qui soit du même format que l'export ox-json d'emacs.
|
- Proposer une sortie json qui soit du même format que l'export ox-json d'emacs.
|
||||||
|
- Inclure les sous tâches aux catégories
|
||||||
# DONE
|
# DONE
|
|
@ -2,29 +2,28 @@
|
||||||
* convertir un fichier .org vers des données structurées en json
|
* convertir un fichier .org vers des données structurées en json
|
||||||
* @type {*}
|
* @type {*}
|
||||||
*/
|
*/
|
||||||
import fs from 'node-fs';
|
import fs from 'node-fs'
|
||||||
import moment from 'moment';
|
import moment from 'moment'
|
||||||
import * as emoji from "node-emoji";
|
import * as emoji from 'node-emoji'
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* initialize configs
|
* initialize configs
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
const sourceFileName = 'all_tasks.org'
|
const sourceFileName = 'all_tasks.org'
|
||||||
const sourceFilePath = './sources/' + sourceFileName;
|
const sourceFilePath = './sources/' + sourceFileName
|
||||||
const outputAbsolutePath = '~/Nextcloud/ressources/social sorting/output/';
|
const outputAbsolutePath = '~/Nextcloud/ressources/social sorting/output/'
|
||||||
const outputFileNameJson = 'export_' + sourceFileName + '_parsed.json';
|
const outputFileNameJson = 'export_' + sourceFileName + '_parsed.json'
|
||||||
|
|
||||||
let headers = []
|
let headers = []
|
||||||
let tasksObjectsForJsonExport = []
|
let tasksObjectsForJsonExport = []
|
||||||
let headersByKind = {}
|
let headersByKind = {}
|
||||||
let writeJsonAfterParse = false;
|
let writeJsonAfterParse = false
|
||||||
writeJsonAfterParse = true;
|
writeJsonAfterParse = true
|
||||||
moment.locale('FR')
|
moment.locale('FR')
|
||||||
|
|
||||||
const tada = emoji.get("tada");
|
const tada = emoji.get('tada')
|
||||||
const gift = emoji.get("gift");
|
const gift = emoji.get('gift')
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
* fetch the source orgmode file to read its contents
|
* fetch the source orgmode file to read its contents
|
||||||
|
@ -32,43 +31,43 @@ const gift = emoji.get("gift");
|
||||||
|
|
||||||
console.log('---------- parse some org file', sourceFilePath)
|
console.log('---------- parse some org file', sourceFilePath)
|
||||||
if (!sourceFilePath) {
|
if (!sourceFilePath) {
|
||||||
console.error('pas de fichier à ouvrir')
|
console.error('pas de fichier à ouvrir')
|
||||||
}
|
}
|
||||||
fs.stat(sourceFilePath, function (err, stat) {
|
fs.stat(sourceFilePath, function (err, stat) {
|
||||||
if (err == null) {
|
if (err === null) {
|
||||||
console.log(`File ${sourceFilePath} exists`);
|
console.log(`File ${sourceFilePath} exists`)
|
||||||
|
|
||||||
} else if (err.code === 'ENOENT') {
|
} else if (err.code === 'ENOENT') {
|
||||||
// file does not exist
|
// file does not exist
|
||||||
console.error(`le fichier ${sourceFilePath} est introuvable. Impossible d en extraire des infos.`, err);
|
console.error(`le fichier ${sourceFilePath} est introuvable. Impossible d en extraire des infos.`, err)
|
||||||
} else {
|
} else {
|
||||||
console.log('Some other error: ', err.code);
|
console.log('Some other error: ', err.code)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* search elements
|
* search elements
|
||||||
*********************/
|
*********************/
|
||||||
let stateKeywordList = ['SOMEDAY', 'NEXT', 'TODO', 'CANCELLED', 'DONE', 'WAITING'];
|
let stateKeywordList = ['SOMEDAY', 'NEXT', 'TODO', 'CANCELLED', 'DONE', 'WAITING']
|
||||||
let dateKeywordList = ['CREATED', 'SCHEDULED', 'DEADLINE', 'CLOSED', 'Refiled'];
|
let dateKeywordList = ['CREATED', 'SCHEDULED', 'DEADLINE', 'CLOSED', 'Refiled']
|
||||||
let sectionKeywordList = ['PROPERTIES', 'LOGBOOK', 'END'];
|
let sectionKeywordList = ['PROPERTIES', 'LOGBOOK', 'END']
|
||||||
|
|
||||||
let propertiesSection = {} // TODO properties listing
|
let propertiesSection = {} // TODO properties listing
|
||||||
let logBookSection = {} // TODO logbook listing
|
let logBookSection = {} // TODO logbook listing
|
||||||
|
|
||||||
let statistics = {
|
let statistics = {
|
||||||
tags: {},
|
tags: {},
|
||||||
words: {},
|
words: {},
|
||||||
dates: {
|
dates: {
|
||||||
havingDate: 0,
|
havingDate: 0,
|
||||||
havingNoDate: 0,
|
havingNoDate: 0,
|
||||||
oldEst: 0,
|
oldEst: 0,
|
||||||
mostRecent: 0,
|
mostRecent: 0,
|
||||||
years: {},
|
years: {},
|
||||||
weeks: {},
|
weeks: {},
|
||||||
months: {},
|
months: {},
|
||||||
days: {}
|
days: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let headerKeywordSearch = '[' + stateKeywordList.join('|') + ']'
|
let headerKeywordSearch = '[' + stateKeywordList.join('|') + ']'
|
||||||
|
@ -77,93 +76,93 @@ let headerKeywordSearch = '[' + stateKeywordList.join('|') + ']'
|
||||||
* @type {{level: string, header: string, dates: {CREATED: string, DONE: string, REFILED: string}, state: string, content: string, properties: {}, tags: [], tagsInherited: []}}
|
* @type {{level: string, header: string, dates: {CREATED: string, DONE: string, REFILED: string}, state: string, content: string, properties: {}, tags: [], tagsInherited: []}}
|
||||||
*/
|
*/
|
||||||
let task = {
|
let task = {
|
||||||
header: "",
|
header: '',
|
||||||
level: "",
|
level: '',
|
||||||
corpus: "",
|
corpus: '',
|
||||||
state: "",
|
state: '',
|
||||||
tags: [],
|
tags: [],
|
||||||
children: [], // TODO list children tasks with a reference to the parent when level is superior to previous task
|
children: [], // TODO list children tasks with a reference to the parent when level is superior to previous task
|
||||||
tagsInherited: [], // TODO inherit tags
|
tagsInherited: [], // TODO inherit tags
|
||||||
dates: {
|
dates: {
|
||||||
havingDate: 0,
|
havingDate: 0,
|
||||||
havingNoDate: 0,
|
havingNoDate: 0,
|
||||||
oldEst: 0,
|
oldEst: 0,
|
||||||
mostRecent: 0,
|
mostRecent: 0,
|
||||||
years: {},
|
years: {},
|
||||||
weeks: {},
|
weeks: {},
|
||||||
months: {},
|
months: {},
|
||||||
days: {},
|
days: {},
|
||||||
},
|
},
|
||||||
logbook: {},
|
logbook: {},
|
||||||
properties: {},
|
properties: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
let isHeader = false;
|
let isHeader = false
|
||||||
let isProperty = false;
|
let isProperty = false
|
||||||
let isLogbook = false;
|
let isLogbook = false
|
||||||
let isFirst = true;
|
let isFirst = true
|
||||||
|
|
||||||
// init first task object as empty clone
|
// init first task object as empty clone
|
||||||
let currentTask = Object.create(task);
|
let currentTask = Object.create(task)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add to tasks to export and refresh current task
|
* add to tasks to export and refresh current task
|
||||||
*/
|
*/
|
||||||
function addAndRefreshCurrentTask() {
|
function addAndRefreshCurrentTask () {
|
||||||
|
|
||||||
makeWordsStatistics(currentTask.header.trim())
|
makeWordsStatistics(currentTask.header.trim())
|
||||||
makeWordsStatistics(currentTask.corpus.trim())
|
makeWordsStatistics(currentTask.corpus.trim())
|
||||||
|
|
||||||
tasksObjectsForJsonExport.push(currentTask)
|
tasksObjectsForJsonExport.push(currentTask)
|
||||||
// réinitialisation de tâche pour remplir de nouveau
|
// réinitialisation de tâche pour remplir de nouveau
|
||||||
currentTask = Object.create(task);
|
currentTask = Object.create(task)
|
||||||
currentTask.dates = {};
|
currentTask.dates = {}
|
||||||
currentTask.tags = [];
|
currentTask.tags = []
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeWordsStatistics(sentence) {
|
function makeWordsStatistics (sentence) {
|
||||||
let split = sentence.split(' ');
|
let split = sentence.split(' ')
|
||||||
if (split && split.length) {
|
if (split && split.length) {
|
||||||
|
|
||||||
split.forEach(word => {
|
split.forEach(word => {
|
||||||
if (!statistics.words[word]) {
|
if (!statistics.words[word]) {
|
||||||
statistics.words[word] = 0
|
statistics.words[word] = 0
|
||||||
}
|
}
|
||||||
statistics.words[word]++
|
statistics.words[word]++
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dateStats = {
|
const dateStats = {
|
||||||
created: 0,
|
created: 0,
|
||||||
refiled: 0,
|
refiled: 0,
|
||||||
closed: 0,
|
closed: 0,
|
||||||
cancelled: 0,
|
cancelled: 0,
|
||||||
scheduled: 0,
|
scheduled: 0,
|
||||||
deadline: 0,
|
deadline: 0,
|
||||||
tasks_done: []
|
tasks_done: []
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillPeriodTime(periodStat, keyword){
|
function fillPeriodTime (periodStat, keyword) {
|
||||||
|
|
||||||
if (keyword === 'CLOSED') {
|
if (keyword === 'CLOSED') {
|
||||||
periodStat.closed++;
|
periodStat.closed++
|
||||||
}
|
}
|
||||||
if (keyword === 'CREATED') {
|
if (keyword === 'CREATED') {
|
||||||
periodStat.created++;
|
periodStat.created++
|
||||||
}
|
}
|
||||||
if (keyword === 'Refiled') {
|
if (keyword === 'Refiled') {
|
||||||
periodStat.refiled++;
|
periodStat.refiled++
|
||||||
}
|
}
|
||||||
if (keyword === 'CANCELLED') {
|
if (keyword === 'CANCELLED') {
|
||||||
periodStat.cancelled++;
|
periodStat.cancelled++
|
||||||
}
|
}
|
||||||
if (keyword === 'SCHEDULED') {
|
if (keyword === 'SCHEDULED') {
|
||||||
periodStat.scheduled++;
|
periodStat.scheduled++
|
||||||
}
|
}
|
||||||
if (keyword === 'DEADLINE') {
|
if (keyword === 'DEADLINE') {
|
||||||
periodStat.deadline++;
|
periodStat.deadline++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,60 +170,59 @@ function fillPeriodTime(periodStat, keyword){
|
||||||
* @param keyword
|
* @param keyword
|
||||||
* @param dateFoundElement
|
* @param dateFoundElement
|
||||||
*/
|
*/
|
||||||
function statisticDateFill(keyword, dateFoundElement, header) {
|
function statisticDateFill (keyword, dateFoundElement, header) {
|
||||||
|
|
||||||
// décompte par années
|
// décompte par années
|
||||||
|
|
||||||
let convertedDate = new Date(dateFoundElement)
|
let convertedDate = new Date(dateFoundElement)
|
||||||
let yearOfDate = convertedDate.getFullYear()
|
let yearOfDate = convertedDate.getFullYear()
|
||||||
let monthOfDate = yearOfDate + '-' + convertedDate.getMonth()
|
let monthOfDate = yearOfDate + '-' + convertedDate.getMonth()
|
||||||
// add zeros
|
// add zeros
|
||||||
let convertedWeek = moment(convertedDate).week() < 10 ? '0' + moment(convertedDate).week() : moment(convertedDate).week()
|
let convertedWeek = moment(convertedDate).week() < 10 ? '0' + moment(convertedDate).week() : moment(convertedDate).week()
|
||||||
let weekOfDate = yearOfDate + '-' + convertedWeek
|
let weekOfDate = yearOfDate + '-' + convertedWeek
|
||||||
|
|
||||||
let convertedMonth = convertedDate.getMonth() < 10 ? '0' + convertedDate.getMonth() : convertedDate.getMonth()
|
let convertedMonth = convertedDate.getMonth() < 10 ? '0' + convertedDate.getMonth() : convertedDate.getMonth()
|
||||||
let convertedDay = convertedDate.getDay() < 10 ? '0' + convertedDate.getDay() : convertedDate.getDay()
|
let convertedDay = convertedDate.getDay() < 10 ? '0' + convertedDate.getDay() : convertedDate.getDay()
|
||||||
let dayOfDate = convertedDate.getFullYear() + '-' + convertedMonth + '-' + convertedDay
|
let dayOfDate = convertedDate.getFullYear() + '-' + convertedMonth + '-' + convertedDay
|
||||||
|
|
||||||
if (!statistics.dates.years[yearOfDate]) {
|
if (!statistics.dates.years[yearOfDate]) {
|
||||||
statistics.dates.years[yearOfDate] = Object.create(dateStats)
|
statistics.dates.years[yearOfDate] = Object.create(dateStats)
|
||||||
}
|
}
|
||||||
fillPeriodTime(statistics.dates.years[yearOfDate], keyword)
|
fillPeriodTime(statistics.dates.years[yearOfDate], keyword)
|
||||||
|
|
||||||
// par année-semaine
|
// par année-semaine
|
||||||
if (!statistics.dates.weeks[weekOfDate]) {
|
if (!statistics.dates.weeks[weekOfDate]) {
|
||||||
statistics.dates.weeks[weekOfDate] = Object.create(dateStats)
|
statistics.dates.weeks[weekOfDate] = Object.create(dateStats)
|
||||||
}
|
}
|
||||||
fillPeriodTime(statistics.dates.weeks[weekOfDate], keyword)
|
fillPeriodTime(statistics.dates.weeks[weekOfDate], keyword)
|
||||||
statistics.dates.weeks[weekOfDate].tasks_done.push(header)
|
statistics.dates.weeks[weekOfDate].tasks_done.push(header)
|
||||||
// décompte par mois
|
// décompte par mois
|
||||||
if (!statistics.dates.months[monthOfDate]) {
|
if (!statistics.dates.months[monthOfDate]) {
|
||||||
statistics.dates.months[monthOfDate] = Object.create(dateStats)
|
statistics.dates.months[monthOfDate] = Object.create(dateStats)
|
||||||
}
|
}
|
||||||
fillPeriodTime(statistics.dates.months[monthOfDate], keyword)
|
fillPeriodTime(statistics.dates.months[monthOfDate], keyword)
|
||||||
|
|
||||||
// décompte par jours
|
// décompte par jours
|
||||||
|
|
||||||
if (!statistics.dates.days[dayOfDate]) {
|
if (!statistics.dates.days[dayOfDate]) {
|
||||||
statistics.dates.days[dayOfDate] = Object.create(dateStats)
|
statistics.dates.days[dayOfDate] = Object.create(dateStats)
|
||||||
}
|
}
|
||||||
fillPeriodTime(statistics.dates.days[dayOfDate], keyword)
|
fillPeriodTime(statistics.dates.days[dayOfDate], keyword)
|
||||||
statistics.dates.days[dayOfDate].tasks_done.push(header)
|
statistics.dates.days[dayOfDate].tasks_done.push(header)
|
||||||
}
|
}
|
||||||
|
|
||||||
function findOldestDate(currentDate) {
|
function findOldestDate (currentDate) {
|
||||||
// trouver la plus ancienne date
|
// trouver la plus ancienne date
|
||||||
|
|
||||||
|
if (!statistics.dates.oldEst) {
|
||||||
if (!statistics.dates.oldEst) {
|
statistics.dates.oldEst = currentDate
|
||||||
statistics.dates.oldEst = currentDate;
|
} else {
|
||||||
} else {
|
var beginningTime = moment(statistics.dates.oldEst)
|
||||||
var beginningTime = moment(statistics.dates.oldEst);
|
var endTime = moment(currentDate)
|
||||||
var endTime = moment(currentDate);
|
if (!beginningTime.isBefore(endTime)) {
|
||||||
if (!beginningTime.isBefore(endTime)) {
|
statistics.dates.oldEst = currentDate
|
||||||
statistics.dates.oldEst = currentDate;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
|
@ -232,208 +230,199 @@ function findOldestDate(currentDate) {
|
||||||
*********************/
|
*********************/
|
||||||
fs.readFile(sourceFilePath, 'utf8', function (err, data) {
|
fs.readFile(sourceFilePath, 'utf8', function (err, data) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return console.log(err)
|
||||||
|
}
|
||||||
|
console.log(' parsing...')
|
||||||
|
// parcourir chaque ligne du fichier org
|
||||||
|
let everyline = data.split('\n')
|
||||||
|
|
||||||
if (err) {
|
// trouver les entêtes toutes les lignes qui commencent par * et espace.
|
||||||
return console.log(err);
|
|
||||||
}
|
|
||||||
console.log(" parsing...")
|
|
||||||
// parcourir chaque ligne du fichier org
|
|
||||||
let everyline = data.split('\n');
|
|
||||||
|
|
||||||
// trouver les entêtes toutes les lignes qui commencent par * et espace.
|
everyline.forEach((line) => {
|
||||||
|
|
||||||
everyline.forEach((line) => {
|
// gérer la création d'objets définissant les tâches et leurs propriétés
|
||||||
|
if (line.match(/^\*+? /)) {
|
||||||
|
// add last task to export list
|
||||||
|
if (!isFirst) {
|
||||||
|
|
||||||
|
addAndRefreshCurrentTask()
|
||||||
|
} else {
|
||||||
|
isFirst = false
|
||||||
|
}
|
||||||
|
|
||||||
// gérer la création d'objets définissant les tâches et leurs propriétés
|
isHeader = true
|
||||||
if (line.match(/^\*+? /)) {
|
// compter les étoiles pour trouver le niveau du header
|
||||||
// add last task to export list
|
if (line.match(/\*/g)) {
|
||||||
if (!isFirst) {
|
|
||||||
|
|
||||||
addAndRefreshCurrentTask();
|
let match = line.match(/\*/g)
|
||||||
} else {
|
currentTask.level = match.length
|
||||||
isFirst = false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
isHeader = true;
|
// create a new task
|
||||||
// compter les étoiles pour trouver le niveau du header
|
|
||||||
if (line.match(/\*/g)) {
|
|
||||||
|
|
||||||
let match = line.match(/\*/g);
|
headers.push(cleanHeader(line))
|
||||||
currentTask.level = match.length
|
currentTask.header = cleanHeader(line)
|
||||||
}
|
stateKeywordList.forEach(keyword => {
|
||||||
|
let keywordIsFound = lineHasKeyword(line, keyword)
|
||||||
|
|
||||||
// create a new task
|
if (keywordIsFound) {
|
||||||
|
currentTask.state = keyword
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// trouver les tags
|
||||||
|
let tagsList = line.match(/\:([\w\_]*)\:/g)
|
||||||
|
if (tagsList) {
|
||||||
|
tagsList = tagsList[0]
|
||||||
|
let tagList = tagsList.split(':')
|
||||||
|
if (tagList.length) {
|
||||||
|
|
||||||
headers.push(cleanHeader(line))
|
tagList.forEach(tag => {
|
||||||
currentTask.header = cleanHeader(line);
|
if (tag.length > 1) {
|
||||||
stateKeywordList.forEach(keyword => {
|
|
||||||
let keywordIsFound = lineHasKeyword(line, keyword)
|
|
||||||
|
|
||||||
if (keywordIsFound) {
|
if (!statistics.tags[tag]) {
|
||||||
currentTask.state = keyword
|
statistics.tags[tag] = 0
|
||||||
}
|
}
|
||||||
})
|
statistics.tags[tag]++
|
||||||
|
|
||||||
|
currentTask.tags.push(tag)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// trouver les tags
|
// ------------- fin des recherches dans la ligne de Header -------------
|
||||||
let tagsList = line.match(/\:([\w\_]*)\:/g)
|
} else {
|
||||||
if (tagsList) {
|
isHeader = false
|
||||||
tagsList = tagsList[0];
|
}
|
||||||
let tagList = tagsList.split(':');
|
// examen des lignes de corps de tâche, ou de corps de section suite au header.
|
||||||
if (tagList.length) {
|
// classer les dates de création, cloture, et de logbook
|
||||||
|
let dateFound = searchDate(line)
|
||||||
|
if (dateFound) {
|
||||||
|
/**
|
||||||
|
* we have found a date in the current line
|
||||||
|
*/
|
||||||
|
|
||||||
tagList.forEach(tag => {
|
statistics.dates.havingDate += 1
|
||||||
if (tag.length > 1) {
|
|
||||||
|
|
||||||
if (!statistics.tags[tag]) {
|
dateKeywordList.forEach(keyword => {
|
||||||
statistics.tags[tag] = 0
|
if (lineHasSubstring(line, keyword)) {
|
||||||
}
|
if (!currentTask.dates[keyword]) {
|
||||||
statistics.tags[tag]++
|
currentTask.dates[keyword] = ''
|
||||||
|
}
|
||||||
|
|
||||||
currentTask.tags.push(tag)
|
let convertedDate = dateFound[0].substring(0, 10)
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (dateFound[0].length === 15) {
|
||||||
|
// sans heure: "2022-12-21 mer."
|
||||||
|
convertedDate = moment(dateFound[0], 'YYYY-MM-DD ddd')
|
||||||
|
|
||||||
// ------------- fin des recherches dans la ligne de Header -------------
|
} else if (dateFound[0].length === 21) {
|
||||||
} else {
|
// avec heure: "2022-11-01 mar. 00:44"
|
||||||
isHeader = false;
|
convertedDate = moment(dateFound[0], 'YYYY-MM-DD ddd HH:mm')
|
||||||
}
|
}
|
||||||
// examen des lignes de corps de tâche, ou de corps de section suite au header.
|
let formattedDate = moment(convertedDate).format()
|
||||||
// classer les dates de création, cloture, et de logbook
|
// console.log('currentTask.header', currentTask.header)
|
||||||
let dateFound = searchDate(line)
|
statisticDateFill(keyword, convertedDate, currentTask.header)
|
||||||
if (dateFound) {
|
findOldestDate(convertedDate)
|
||||||
/**
|
currentTask.dates[keyword] = formattedDate
|
||||||
* we have found a date in the current line
|
|
||||||
*/
|
|
||||||
|
|
||||||
statistics.dates.havingDate += 1;
|
} else {
|
||||||
|
// console.log('keyword', keyword)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
statistics.dates.havingNoDate += 1
|
||||||
|
if (
|
||||||
|
line.indexOf(dateKeywordList) !== -1 &&
|
||||||
|
line.indexOf(stateKeywordList) !== -1 &&
|
||||||
|
line.indexOf(sectionKeywordList) !== -1
|
||||||
|
) {
|
||||||
|
|
||||||
dateKeywordList.forEach(keyword => {
|
// ajouter le corps complet de la section après le header
|
||||||
if (lineHasSubstring(line, keyword)) {
|
if (line.length && !isHeader) {
|
||||||
if (!currentTask.dates[keyword]) {
|
|
||||||
currentTask.dates[keyword] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
let convertedDate = dateFound[0].substring(0, 10);
|
let cleanedLine = line.replace(/\s\s/g, ' ')
|
||||||
|
cleanedLine = line.replace(/ {2,}/g, ' ')
|
||||||
|
|
||||||
if (dateFound[0].length == 15) {
|
cleanedLine = cleanedLine.trim()
|
||||||
// sans heure: "2022-12-21 mer."
|
|
||||||
convertedDate = moment(dateFound[0], 'YYYY-MM-DD ddd')
|
|
||||||
|
|
||||||
} else if (dateFound[0].length == 21) {
|
currentTask.corpus += `${cleanedLine}
|
||||||
// avec heure: "2022-11-01 mar. 00:44"
|
|
||||||
convertedDate = moment(dateFound[0], 'YYYY-MM-DD ddd HH:mm')
|
|
||||||
}
|
|
||||||
let formattedDate = moment(convertedDate).format()
|
|
||||||
console.log('currentTask.header', currentTask.header)
|
|
||||||
statisticDateFill(keyword, convertedDate, currentTask.header)
|
|
||||||
findOldestDate(convertedDate)
|
|
||||||
currentTask.dates[keyword] = formattedDate;
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// console.log('keyword', keyword)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
statistics.dates.havingNoDate += 1;
|
|
||||||
if (
|
|
||||||
line.indexOf(dateKeywordList) !== -1 &&
|
|
||||||
line.indexOf(stateKeywordList) !== -1 &&
|
|
||||||
line.indexOf(sectionKeywordList) !== -1
|
|
||||||
) {
|
|
||||||
|
|
||||||
// ajouter le corps complet de la section après le header
|
|
||||||
if (line.length && !isHeader) {
|
|
||||||
|
|
||||||
let cleanedLine = line.replace(/\s\s/g, ' ');
|
|
||||||
cleanedLine = line.replace(/ {2,}/g, ' ')
|
|
||||||
|
|
||||||
cleanedLine = cleanedLine.trim()
|
|
||||||
|
|
||||||
currentTask.corpus += `${cleanedLine}
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ajouter la dernière tâche parsée
|
||||||
|
addAndRefreshCurrentTask()
|
||||||
|
|
||||||
// ajouter la dernière tâche parsée
|
console.log('tasks : ', tasksObjectsForJsonExport.length)
|
||||||
addAndRefreshCurrentTask();
|
console.log(tada + ' parsing fini ' + tada)
|
||||||
|
|
||||||
console.log(tada+ " parsing fini "+ tada)
|
// ranger par valeur décroissante les tags
|
||||||
|
|
||||||
// ranger par valeur décroissante les tags
|
let sorted_stats = []
|
||||||
|
// rangement par valeur et par date
|
||||||
|
console.log('write file ', outputAbsolutePath, outputFileNameJson)
|
||||||
|
statistics.dates.years = sortByKey(statistics.dates.years)
|
||||||
|
statistics.dates.weeks = sortByKey(statistics.dates.weeks)
|
||||||
|
statistics.dates.months = sortByKey(statistics.dates.months)
|
||||||
|
statistics.dates.days = sortByKey(statistics.dates.days)
|
||||||
|
|
||||||
let sorted_stats = [];
|
statistics = sortByKey(statistics)
|
||||||
// rangement par valeur et par date
|
|
||||||
console.log('write file ', outputAbsolutePath, outputFileNameJson);
|
|
||||||
statistics.dates.years = sortByKey(statistics.dates.years)
|
|
||||||
statistics.dates.weeks = sortByKey(statistics.dates.weeks)
|
|
||||||
statistics.dates.months = sortByKey(statistics.dates.months)
|
|
||||||
statistics.dates.days = sortByKey(statistics.dates.days)
|
|
||||||
|
|
||||||
statistics = sortByKey(statistics)
|
const jsonContent = {
|
||||||
|
statistics: {
|
||||||
|
lines_count: everyline.length,
|
||||||
|
headers_count: headers.length,
|
||||||
|
statistics
|
||||||
|
},
|
||||||
|
meta_data: {
|
||||||
|
author: '@tykayn@mastodon.Cipherbliss.com',
|
||||||
|
generated_at: new Date(),
|
||||||
|
generated_from_file: sourceFilePath + sourceFileName,
|
||||||
|
sources: 'https://forge.chapril.org/tykayn/org-report-stats.git'
|
||||||
|
},
|
||||||
|
tasks_list: tasksObjectsForJsonExport
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeJsonAfterParse) {
|
||||||
|
|
||||||
const jsonContent = {
|
writeFileInOuputFolderFromJsonObject(outputFileNameJson, jsonContent)
|
||||||
statistics: {
|
}
|
||||||
lines_count: everyline.length,
|
|
||||||
headers_count: headers.length,
|
|
||||||
statistics
|
|
||||||
},
|
|
||||||
meta_data: {
|
|
||||||
author: '@tykayn@mastodon.Cipherbliss.com',
|
|
||||||
generated_at: new Date(),
|
|
||||||
generated_from_file: sourceFilePath + sourceFileName,
|
|
||||||
sources: 'https://forge.chapril.org/tykayn/org-report-stats.git'
|
|
||||||
},
|
|
||||||
tasks_list: tasksObjectsForJsonExport
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (writeJsonAfterParse) {
|
|
||||||
|
|
||||||
writeFileInOuputFolderFromJsonObject(outputFileNameJson, jsonContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function lineHasKeyword (line, keyword = 'TODO') {
|
||||||
|
|
||||||
function lineHasKeyword(line, keyword = 'TODO') {
|
let isFound = (line.indexOf('* ' + keyword) !== -1)
|
||||||
|
if (isFound) {
|
||||||
let isFound = (line.indexOf('* ' + keyword) !== -1)
|
createNewHeaderKind(keyword)
|
||||||
if (isFound) {
|
headersByKind[keyword].push(line)
|
||||||
createNewHeaderKind(keyword)
|
if (!statistics[keyword]) {
|
||||||
headersByKind[keyword].push(line);
|
statistics[keyword] = 0
|
||||||
if (!statistics[keyword]) {
|
}
|
||||||
statistics[keyword] = 0
|
statistics[keyword]++
|
||||||
}
|
}
|
||||||
statistics[keyword]++
|
return isFound
|
||||||
}
|
|
||||||
return isFound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function lineHasSubstring(line, keyword) {
|
function lineHasSubstring (line, keyword) {
|
||||||
let isFound = (line.indexOf(keyword) !== -1)
|
let isFound = (line.indexOf(keyword) !== -1)
|
||||||
if (!statistics[keyword]) {
|
if (!statistics[keyword]) {
|
||||||
statistics[keyword] = 0
|
statistics[keyword] = 0
|
||||||
}
|
}
|
||||||
statistics[keyword]++
|
statistics[keyword]++
|
||||||
|
|
||||||
return isFound
|
return isFound
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewHeaderKind(keyword) {
|
function createNewHeaderKind (keyword) {
|
||||||
if (!headersByKind[keyword]) {
|
if (!headersByKind[keyword]) {
|
||||||
headersByKind[keyword] = [];
|
headersByKind[keyword] = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -443,22 +432,22 @@ function createNewHeaderKind(keyword) {
|
||||||
* @param line
|
* @param line
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
function searchDate(line) {
|
function searchDate (line) {
|
||||||
// return line.match(/[(\d{4}\-\d{2}\-\d{2} ?\d{2}?\:?\d{2}?\:?\d{2}?)(\d{4}\-\d{2}\-\d{2})]/)
|
// return line.match(/[(\d{4}\-\d{2}\-\d{2} ?\d{2}?\:?\d{2}?\:?\d{2}?)(\d{4}\-\d{2}\-\d{2})]/)
|
||||||
let simpleDay = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.?/)
|
let simpleDay = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.?/)
|
||||||
let simpleDayHour = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.? \d{2}\:\d{2}/)
|
let simpleDayHour = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.? \d{2}\:\d{2}/)
|
||||||
let simpleDayHourSec = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.? \d{2}\:\d{2}\:\d{2}/)
|
let simpleDayHourSec = line.match(/\d{4}\-\d{2}\-\d{2} \w{3}?\.? \d{2}\:\d{2}\:\d{2}/)
|
||||||
|
|
||||||
if (simpleDayHourSec) {
|
if (simpleDayHourSec) {
|
||||||
return simpleDayHourSec;
|
return simpleDayHourSec
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simpleDayHour) {
|
if (simpleDayHour) {
|
||||||
return simpleDayHour;
|
return simpleDayHour
|
||||||
}
|
}
|
||||||
if (simpleDay) {
|
if (simpleDay) {
|
||||||
return simpleDay;
|
return simpleDay
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,17 +455,17 @@ function searchDate(line) {
|
||||||
* get the cleaned content of the header
|
* get the cleaned content of the header
|
||||||
* @param line
|
* @param line
|
||||||
*/
|
*/
|
||||||
function cleanHeader(line) {
|
function cleanHeader (line) {
|
||||||
|
|
||||||
line = '' + line;
|
line = '' + line
|
||||||
stateKeywordList.forEach(keyword => {
|
stateKeywordList.forEach(keyword => {
|
||||||
line = line.replace(keyword, '')
|
line = line.replace(keyword, '')
|
||||||
})
|
})
|
||||||
line = line.replace(/\** /, '');
|
line = line.replace(/\** /, '')
|
||||||
line = line.replace(/\[.*\]/g, '');
|
line = line.replace(/\[.*\]/g, '')
|
||||||
line = line.replace(/\:.*\:/g, '');
|
line = line.replace(/\:.*\:/g, '')
|
||||||
line = line.replace(' ', '');
|
line = line.replace(' ', '')
|
||||||
return line.trim();
|
return line.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -484,14 +473,14 @@ function cleanHeader(line) {
|
||||||
* @param objectStuff
|
* @param objectStuff
|
||||||
* @returns {{}}
|
* @returns {{}}
|
||||||
*/
|
*/
|
||||||
function sortByKey(objectStuff) {
|
function sortByKey (objectStuff) {
|
||||||
return Object.keys(objectStuff).sort().reduce(
|
return Object.keys(objectStuff).sort().reduce(
|
||||||
(obj, key) => {
|
(obj, key) => {
|
||||||
obj[key] = objectStuff[key];
|
obj[key] = objectStuff[key]
|
||||||
return obj;
|
return obj
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -499,32 +488,32 @@ function sortByKey(objectStuff) {
|
||||||
* @param literalobject
|
* @param literalobject
|
||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
function sortByValue(literalobject) {
|
function sortByValue (literalobject) {
|
||||||
|
|
||||||
let sortable = [];
|
let sortable = []
|
||||||
for (var keyName in literalobject) {
|
for (var keyName in literalobject) {
|
||||||
sortable[keyName] = literalobject[keyName];
|
sortable[keyName] = literalobject[keyName]
|
||||||
}
|
}
|
||||||
// return literalobject
|
// return literalobject
|
||||||
return sortable.sort(function (a, b) {
|
return sortable.sort(function (a, b) {
|
||||||
return b[1] - a[1];
|
return b[1] - a[1]
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function writeFileInOuputFolderFromJsonObject(fileName, jsonObjectThing) {
|
export async function writeFileInOuputFolderFromJsonObject (fileName, jsonObjectThing) {
|
||||||
|
|
||||||
// console.log('statistics.dates', statistics.dates)
|
// console.log('statistics.dates', statistics.dates)
|
||||||
|
|
||||||
return await fs.writeFile(
|
return await fs.writeFile(
|
||||||
`${outputAbsolutePath}${fileName}`,
|
`${outputAbsolutePath}${fileName}`,
|
||||||
JSON.stringify(jsonObjectThing, null,2),
|
JSON.stringify(jsonObjectThing, null, 2),
|
||||||
"utf8",
|
'utf8',
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(`Error writing file: ${err}`);
|
console.log(`Error writing file: ${err}`)
|
||||||
} else {
|
} else {
|
||||||
console.log(`\n ${gift} File ${fileName} is written successfully!`);
|
console.log(`\n ${gift} File ${fileName} is written successfully!`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
|
@ -12,11 +12,12 @@ import { writeFileInOuputFolderFromJsonObject } from './utils.mjs'
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
// const sourceFileBaseName = 'sms-20180423162531'
|
// const sourceFileBaseName = 'sms-20180423162531'
|
||||||
const sourceFileBaseName = 'sms'
|
const sourceFileBaseName = 'sms-20230921224605'
|
||||||
const sourceFileName = `${sourceFileBaseName}.xml`
|
const sourceFileName = `${sourceFileBaseName}.xml`
|
||||||
const outputFileJson = `${sourceFileBaseName}.json`
|
const outputFileJson = `${sourceFileBaseName}.json`
|
||||||
const outputFileCsv = `${sourceFileBaseName}.tsv`
|
const outputFileCsv = `${sourceFileBaseName}.csv`
|
||||||
const folder_base = '/home/tykayn/Nextcloud/ressources/social sorting/'
|
const folder_base = '/home/tykayn/Nextcloud/ressources/social sorting/'
|
||||||
|
const csv_separator = ';'
|
||||||
|
|
||||||
const outputFileJsonPathFull = `${folder_base}output/${outputFileJson}`
|
const outputFileJsonPathFull = `${folder_base}output/${outputFileJson}`
|
||||||
const sourceFileJson = `${folder_base}output/${outputFileJson}`
|
const sourceFileJson = `${folder_base}output/${outputFileJson}`
|
||||||
|
@ -54,46 +55,49 @@ function convertJsonToCsvAndPersistTSVFile (jsonFilePath, outputFileTSVName) {
|
||||||
|
|
||||||
console.log('convert', folder_base+'output/' + jsonFilePath)
|
console.log('convert', folder_base+'output/' + jsonFilePath)
|
||||||
fs.readFile(folder_base+'output/' + jsonFilePath, 'utf8', function (err, data) {
|
fs.readFile(folder_base+'output/' + jsonFilePath, 'utf8', function (err, data) {
|
||||||
|
data = JSON.parse(data)
|
||||||
console.log('data', data.length)
|
console.log('data', data.length)
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
|
|
||||||
'amount\t' +
|
'amount' + csv_separator + ''+
|
||||||
'content\t' +
|
'content' + csv_separator +''+
|
||||||
'description\t' +
|
'description' + csv_separator +
|
||||||
'destination\t' +
|
'destination' + csv_separator +
|
||||||
'end\t' +
|
'end' + csv_separator +
|
||||||
'kind of activity\t' +
|
'kind of activity' + csv_separator +
|
||||||
'person\t' +
|
'person' + csv_separator +
|
||||||
'place\t' +
|
'place' + csv_separator +
|
||||||
'source\t' +
|
'source' + csv_separator +
|
||||||
'start\t' +
|
'start' + csv_separator +
|
||||||
'unique id\t' +
|
'unique id' + csv_separator +
|
||||||
'url\t'
|
'url' + csv_separator
|
||||||
]
|
]
|
||||||
data = JSON.parse(data)
|
|
||||||
// console.log('data.length', data.length)
|
// console.log('data', data)
|
||||||
console.log('data', Object.keys(data))
|
// console.log('data other ', data)
|
||||||
let smslist = data['elements'][1]['elements']
|
console.log('data.length', data['elements'].length)
|
||||||
|
console.log('data name', data['elements'][2]['elements'].length)
|
||||||
|
let smslist = data['elements'][2]['elements']
|
||||||
|
// let smslist = data['smses']
|
||||||
if (smslist) {
|
if (smslist) {
|
||||||
smslist.forEach(item => {
|
smslist.forEach(item => {
|
||||||
|
|
||||||
// convert all fields to common event description
|
// convert all fields to common event description
|
||||||
events.push(
|
events.push(
|
||||||
'\t' +
|
''+csv_separator +
|
||||||
item.attributes.body.replace('\n', ' ') + '\t' +
|
item.attributes.body + csv_separator +
|
||||||
'sms ' + item.attributes.address + ' le ' + item.attributes.readable_date + '\t' +
|
'sms ' + item.attributes.address + ' le ' + item.attributes.readable_date + csv_separator +
|
||||||
item.attributes.address + '\t' +
|
item.attributes.address + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
item.attributes.contact_name + '\t' +
|
item.attributes.contact_name + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
'' + '\t' +
|
'' + csv_separator +
|
||||||
'' + '\t'
|
'' + csv_separator
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
// // console.log('events', events)
|
// // console.log('events', events)
|
||||||
|
@ -122,10 +126,11 @@ function openSourceFile () {
|
||||||
fs.readFile(sourceFilePath, 'utf8', function (err, data) {
|
fs.readFile(sourceFilePath, 'utf8', function (err, data) {
|
||||||
// // console.log('data', data)
|
// // console.log('data', data)
|
||||||
var jsonConversion = convert.xml2json(data)
|
var jsonConversion = convert.xml2json(data)
|
||||||
console.log('jsonConversion keys', Object.keys(jsonConversion))
|
// console.log('jsonConversion 0', Object.keys(jsonConversion['elements']))
|
||||||
// console.log('jsonConversion.length', parseFloat(jsonConversion.length / 1024 / 1024, 2), 'Mo')
|
// console.log('jsonConversion.length', parseFloat(jsonConversion.length / 1024 / 1024, 2), 'Mo')
|
||||||
|
|
||||||
writeFileInOuputFolderFromJsonObject(outputFileJson, JSON.parse( jsonConversion))
|
// writeFileInOuputFolderFromJsonObject(outputFileJson, JSON.parse( jsonConversion))
|
||||||
|
writeFileInOuputFolderFromJsonObject(outputFileJson, JSON.parse(jsonConversion))
|
||||||
convertJsonToCsvAndPersistTSVFile(outputFileJson, outputFileCsv)
|
convertJsonToCsvAndPersistTSVFile(outputFileJson, outputFileCsv)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,11 +20,11 @@ export async function writeFileInOuputFolderFromJsonObject (fileName, jsonObject
|
||||||
// console.log('statistics.dates', statistics.dates)
|
// console.log('statistics.dates', statistics.dates)
|
||||||
let fullpath = `${outputAbsolutePath}${fileName}`
|
let fullpath = `${outputAbsolutePath}${fileName}`
|
||||||
|
|
||||||
return await fs.writeFile(
|
return await fs.writeFileSync(
|
||||||
fullpath,
|
fullpath,
|
||||||
JSON.stringify(jsonObjectThing, null, 2),
|
// JSON.stringify(jsonObjectThing, null, 2),
|
||||||
// JSON.stringify(jsonObjectThing).replace('\n',''),
|
JSON.stringify(jsonObjectThing).replace('\n',''),
|
||||||
'utf8',
|
'UTF8',
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(`Error writing file: ${err}`)
|
console.log(`Error writing file: ${err}`)
|
||||||
|
|
Loading…
Reference in New Issue