Przejdź do głównej treści

YAML tester

Obraz Logo YAML

YAML tester to lekka aplikacja webowa umożliwiająca szybkie testowanie i debugowanie plików YAML bez potrzeby uruchamiania lokalnego środowiska.

Zbudowana w oparciu o bibliotekę Spyc (https://github.com/mustangostang/spyc), parser YAML dla PHP, oferuje zgodność z najczęściej używaną składnią YAML 1.2, obsługującą m.in.:

  • zagnieżdżone struktury tablic i obiektów,
  • mapy klucz-wartość,
  • typy skalarne i sekwencje,
  • wcięcia i białe znaki zgodne z konwencją YAML.

Funkcje:

  • Parser oparty na Spyc – szybki, stabilny i battle-tested.
  • Bezpieczne środowisko testowe – kod nie jest zapisywany ani przesyłany dalej.
  • Informacja zwrotna w czasie rzeczywistym – błędy składni zwracane natychmiast.
  • Zgodność z PHP – wyniki walidacji odpowiadają strukturze, jaką otrzymasz przy użyciu Spyc::YAMLLoad().

Dla kogo?

Dla programistów PHP, DevOpsów, administratorów systemów i wszystkich, którzy chcą błyskawicznie zweryfikować poprawność i strukturę danych YAML przed wdrożeniem ich do aplikacji.

Przykładowy plik YAML do testowania

app:
  name: YAML tester
  version: 1.0.0
  author: Jan Kowalski
  features:
    - Walidacja składni
    - Parser oparty na Spyc
    - Obsługa struktur zagnieżdżonych
    - Przejrzyste błędy
database:
  host: localhost
  port: 3306
  username: root
  password: secret
  options:
    reconnect: true
    timeout: 30
debug: true

Wynik

{{ result }}
{{time}} ms

Kod po stronie przeglądarki

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.css">
<link rel="stylesheet" href="http://www.dariuszrorat.ugu.pl/assets/css/codemirror/theme/golden.css">
<link rel="stylesheet" href="http://www.dariuszrorat.ugu.pl/assets/css/codemirror/themes.css">
<div id="app">
    <div class="row mb-3">
        <div class="col-12">
            <label for="yaml" class="form-label">Tekst YAML</label>
            <textarea id="yaml" class="form-control"></textarea>                    
        </div>
    </div>
    <div class="row mb-3">
        <div class="col-3">
            <label for="format" class="form-label">Format wyjściowy</label>
            <select id="format" class="form-select" v-model="format">
                <option value="php">PHP</option>
                <option value="json">JSON</option>
            </select>                    
        </div>
    </div>
    <div class="mb-3">
        <button class="btn btn-primary" @click="convert"><i class="bi bi-play-fill"></i> Wykonaj</button>
    </div>    
    <div class="mb-3" v-if="success">        
        <h2>Wynik</h2>
        <pre><code :class="'language-'+format" id="output">{{ result }}</code></pre>
    </div>  
    <div class="progress mb-3" v-if="success">
        <div class="progress-bar" role="progressbar" :style="'width: '+ percent + '%'" :class="bgColor">
        {{time}} ms
        </div>
    </div>    
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/yaml/yaml.min.js"></script>
<script>
// Max 10ms expected time    
const MAX_EXPECTED_TIME = 10;
function escapeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}
  
var vm = null;
document.addEventListener('DOMContentLoaded', function() {    
vm = new Vue({
    el: '#app',
    data: {
        yaml: '',
        format: 'php',
        result: '',
        success: false,
        time: 0,
        bgColor: 'text-bg-primary',
        percent: 0        
    },
    updated() {
        this.$nextTick(function () {
            const el = document.getElementById('output');                
            if (el)
            {
                if (el.hasAttribute('data-highlighted'))
                    el.removeAttribute('data-highlighted');
                if (el.hasAttribute('data-highlighter'))
                    el.removeAttribute('data-highlighter');
                if (el.classList.contains('hljs'))
                    el.classList.remove(...Array.from(el.classList).filter(cls => cls.startsWith('hljs')));
                el.innerHTML = escapeHTML(el.textContent);
                hljs.highlightElement(el);
            }
        });    
    },
    methods: {
       convert() {
        var self = this;
        self.result = '';    
        
        var data = {
            yaml: self.yaml,
            format: self.format,
            token: '1f9de1297e2a533b016362d4774ecfd674749377'
        };
        
        self.success = false;
        axios.post(urlSite('public/ajax/app/exec/27'), data, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})        
          .then(function (response) {              
              self.result = response.data.data;
              const duration = response.data.time;
              self.time = duration.toFixed(2);
              self.percent = Math.min((duration / MAX_EXPECTED_TIME) * 100, 100).toFixed(0);    

              if       (self.percent <= 25)                         self.bgColor = 'text-bg-success';
              else if ((self.percent > 25) && (self.percent <= 50)) self.bgColor = 'text-bg-info';
              else if ((self.percent > 50) && (self.percent <= 75)) self.bgColor = 'text-bg-warning';
              else                                                  self.bgColor = 'text-bg-danger';
            
              self.success = true;
        }).catch(function(error) {
              self.success = false;
              BootstrapToast.show({title: 'Błąd', message: 'Przepraszamy, ale wystąpił błąd parsowania składni.', when: 'teraz', type: 'text-bg-danger'});
        });
      }
    }    
});

//CodeMirror for textarea
var myTextarea = document.getElementById('yaml');  
var editor = CodeMirror.fromTextArea(myTextarea, {
        lineNumbers: true,
        matchBrackets: true,
        mode: "text/x-yaml",
        indentUnit: 4,
        indentWithTabs: false,
        enterMode: "keep",
        tabMode: "shift",
        extraKeys: {Tab: false, "Shift-Tab": false}
  });
  editor.setSize(null, 500);  
  editor.getWrapperElement().style["font-size"] = "14px";
  editor.refresh();    
  editor.on('change', (args) => { vm.yaml = editor.getValue() } );  
    
  //WCAG missing form label fix  
  codemirrorTextareaIdFix("yaml");  
});    
</script>

Kod po stronie serwera

$yaml = Input::post('yaml', '');
$format = Input::post('format', 'php');
$timediff = 0;
try
{
    $start = microtime(true);
    $data = Format::from_yaml($yaml);
    $end = microtime(true);
    $timediff = ($end - $start) * 1000;
}
catch (Exception $e)
{
    Kohana_Exception::log($e);
    throw HTTP_Exception::factory(500)
        ->as_json();    
}
    
$dump = $format === 'php' ? var_export($data, true) : $data;
$output = [
    'data' => $dump,
    'time' => $timediff,
];

$response = Response::factory()
    ->headers('Content-Type', 'application/json')
    ->status(200)
    ->body(json_encode($output));

echo $response->send_headers()->body();

Tagi

yaml

Dziękujemy!
()

Informacja o cookies

Moja strona internetowa wykorzystuje wyłącznie niezbędne pliki cookies, które są wymagane do jej prawidłowego działania. Nie używam ciasteczek w celach marketingowych ani analitycznych. Korzystając z mojej strony, wyrażasz zgodę na stosowanie tych plików. Możesz dowiedzieć się więcej w mojej polityce prywatności.