Browse Source

Added pandoc as MD-TO-ODT converter

master
Radu Liviu Carjan 3 years ago
parent
commit
f0b57b1244
  1. 46
      app/Http/Controllers/FileController.php
  2. 74
      public/js/app.js
  3. 6
      resources/js/components/ProcessFile/ProcessFile.ts
  4. 3
      resources/js/components/ProcessFile/ProcessFile.vue
  5. 18
      resources/js/services/ApiService.ts
  6. 5
      routes/api.php
  7. 6
      routes/web.php

46
app/Http/Controllers/FileController.php

@ -8,6 +8,8 @@ use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use Illuminate\Support\Str;
use Symfony\Component\Process\Process;
class FileController extends Controller
{
@ -57,4 +59,48 @@ class FileController extends Controller
], 400);
}
}
/**
*
*/
public function convert(): JsonResponse
{
$mdFileContent = request()->input('content');
$tmpFileId = (string) Str::uuid();
Storage::disk('local')->put('tmp/' . $tmpFileId . '.md', $mdFileContent);
$tmpMdFilePath = Storage::path('tmp/' . $tmpFileId . '.md');
$pandoc = new Process([
'pandoc',
'-f',
'markdown',
'-t',
'odt',
$tmpMdFilePath
]);
$pandoc->start();
while ($pandoc->isRunning()) {
//
}
$odtFileContent = $pandoc->getOutput();
Storage::disk('local')->put('tmp/' . $tmpFileId . '.odt', $odtFileContent);
return response()->json([
'path' => 'tmp/' . $tmpFileId . '.odt'
]);
}
/**
*
* @param string $path
* @return mixed
*/
public function download(string $path)
{
return Storage::download($path);
}
}

74
public/js/app.js

@ -2526,6 +2526,36 @@ var ProcessFile = /*#__PURE__*/function (_Vue) {
return runSearchers;
}()
}, {
key: "downloadOdt",
value: function () {
var _downloadOdt = _asyncToGenerator( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee4() {
var response;
return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return this.$api.convertFile(this.processedFileContent);
case 2:
response = _context4.sent;
window.open('http://core.sandd/file/download/' + response.path);
case 4:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
}));
function downloadOdt() {
return _downloadOdt.apply(this, arguments);
}
return downloadOdt;
}()
}]);
return ProcessFile;
@ -2614,6 +2644,7 @@ var ApiService = /*#__PURE__*/function () {
this.apiRoutes = {
file: this.baseUrl + '/api/file',
fileDownload: this.baseUrl + '/api/file/convert',
searchAndDisplace: this.baseUrl + '/search-and-displace'
};
}
@ -2764,6 +2795,44 @@ var ApiService = /*#__PURE__*/function () {
return filterDocument;
}()
}, {
key: "convertFile",
value: function () {
var _convertFile = _asyncToGenerator( /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee4(content) {
var response;
return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.prev = 0;
_context4.next = 3;
return axios__WEBPACK_IMPORTED_MODULE_1___default().post(this.apiRoutes.fileDownload, {
'content': content
});
case 3:
response = _context4.sent;
return _context4.abrupt("return", response.data);
case 7:
_context4.prev = 7;
_context4.t0 = _context4["catch"](0);
throw _context4.t0;
case 10:
case "end":
return _context4.stop();
}
}
}, _callee4, this, [[0, 7]]);
}));
function convertFile(_x5) {
return _convertFile.apply(this, arguments);
}
return convertFile;
}()
}]);
return ApiService;
@ -31492,6 +31561,11 @@ var render = function() {
attrs: {
label: "Download document",
icon: "pi pi-download"
},
on: {
click: function($event) {
return _vm.downloadOdt()
}
}
}),
_vm._v(" "),

6
resources/js/components/ProcessFile/ProcessFile.ts

@ -156,4 +156,10 @@ export default class ProcessFile extends Vue {
2500
);
}
private async downloadOdt()
{
let response = await this.$api.convertFile(this.processedFileContent);
window.open('http://core.sandd/file/download/' + response.path);
}
}

3
resources/js/components/ProcessFile/ProcessFile.vue

@ -46,7 +46,8 @@
<Button
label="Download document"
icon="pi pi-download"
class="p-button-secondary p-button-outlined p-button-sm"/>
class="p-button-secondary p-button-outlined p-button-sm"
@click="downloadOdt()"/>
<Button
label="Run filters"

18
resources/js/services/ApiService.ts

@ -10,6 +10,7 @@ export default class ApiService {
/** @type { [key:string] : string; } */
private readonly apiRoutes = {
file: this.baseUrl + '/api/file',
fileDownload: this.baseUrl + '/api/file/convert',
searchAndDisplace: this.baseUrl + '/search-and-displace'
};
@ -89,4 +90,21 @@ export default class ApiService {
throw err;
}
}
public async convertFile(content:string)
{
try {
let response = await axios.post(
this.apiRoutes.fileDownload,
{
'content': content
}
);
return response.data;
} catch (err) {
throw err;
}
}
}

5
routes/api.php

@ -25,6 +25,11 @@ Route::name('file.')->prefix('file')->group(
FileController::class,
'create'
])->name('create');
Route::post('/convert', [
FileController::class,
'convert'
])->name('convert');
}
);

6
routes/web.php

@ -1,6 +1,7 @@
<?php
use App\Http\Controllers\PagesController;
use App\Http\Controllers\FileController;
use Illuminate\Support\Facades\Route;
/*
@ -19,4 +20,9 @@ Route::get('/', 'HomeController@index');
Route::get('/search-and-displace/{id}', 'SearchAndDisplaceController@show');
Route::post('/search-and-displace', 'SearchAndDisplaceController@store');
Route::get('/file/download/{path}', [
FileController::class,
'download'
])->where('path', '.*')->name('file.download');
Route::webhooks('/webhooks', 'default');
Loading…
Cancel
Save